Android中利用RadioGroup和View实现TabLayout的

我们知道,在使用tabLayout的时候,其下面的标记线google没有直接提供给我们APi去修改它的长度,那么今天来使用<RadioGroup>  和  <RadioButton> 与 <View> 的组合完成我们TabLayout的功能. 

先上效果图.

Android中利用RadioGroup和View实现TabLayout的

这里代码的逻辑很简单,也没有完全封装,只是给大家一个思路,在这个基础上修改很简单,只需要修改布局和简单的代码逻辑即可.

首先来说一下思路.

1,寻找id

2,计算宽度.

3,为view添加TranslateAnimation.

下面来看代码:

1,查找id.

private RadioGroup mBottomButton;//底部按钮父类
private View line;//线
private RadioButton bt1;
private RadioButton bt2;
private RadioButton bt3;
private RadioButton bt4;

public NewsMainBottomView(Context context) {
    super(context);
    LayoutInflater.from(context).inflate(R.layout.news_main_bottom_bt, this);
    mBottomButton = findViewById(R.id.radio_group);
    line = findViewById(R.id.line_view);
    bt1 = findViewById(R.id.rb_one);
    bt2 = findViewById(R.id.rb_two);
    bt3 = findViewById(R.id.rb_three);
    bt4 = findViewById(R.id.rb_four);
    init();
}
private void init(){
    mBottomButton.setOnCheckedChangeListener(this);
}

//设置按钮文字(四个)
public void setTextList(String[] str){
    mTextList = str;
    bt1.setText(mTextList[0]);
    bt2.setText(mTextList[1]);
    bt3.setText(mTextList[2]);
    bt4.setText(mTextList[3]);
    initWidth();
}

上面的代码没什么可说的,这里的bt1-4其实是可以根据传入的tab数量动态创建的,只是想偷个懒,所以写死了.

2,计算宽度.

//初始化宽度
private void initWidth(){
    textWidth = (int) bt1.getPaint().measureText(mTextList[0]);
    final LayoutParams params = new LayoutParams(textWidth, ScreenUtil.dip2px(getContext(), 2));
    //获取单个按钮的宽度
    mBottomButton.post(new Runnable(){
        public void run(){
            viewWidth = mBottomButton.getWidth();
            params.leftMargin = (viewWidth / 4 - textWidth) / 2;
            line.setLayoutParams(params);
        }
    });
}
textWidth就是文字的宽度,因为我的项目的底部的文字的字数是相同的,所以我用了mTextList数组中的第1个数据计算的.

下面是获取一个按钮的宽度,因为在此时,Activity中的调用还是处于onCreate中,所以无法用getWidth()获取到控件的尺寸.有了文字宽度和单个radioButton的宽度,那么文字到radiobutton左侧的宽度也就有了,将这个宽度设置为line的leftMargin.让其初始位置就与第一个tab的文字对其.

3,给line添加translateAnimation.

private int nowTranslatePosition;//当前横线左侧所在x坐标
/**
 * 更新横线的动画
 * @param index 当前选中按钮的下标
 */
public void upDateAnimation(int index){
    //下次移动的x坐标(相对) = radiogroup / 控件的数量 * 选中控件位置的下标 + 一个item中文字到该item左侧的距离(此处没有加此项,因为上面已经为line设置了此项的marginleft)
    int nextTranslatePosition = viewWidth / mTextList.length * index;//点击或滑动后横线需要移动到的x坐标
    if(nowTranslatePosition != nextTranslatePosition){
        TranslateAnimation animation = new TranslateAnimation(nowTranslatePosition, nextTranslatePosition,0,0);
        animation.setFillAfter(true);
        animation.setDuration(animDuration);
        line.startAnimation(animation);
        nowTranslatePosition = nextTranslatePosition;
    }
}
这一步没什么可说的,接着往下看.

@Override
public void onPageSelected(int position) {
    this.currentPosition = position;
    if(position < 6){
        bt1.setChecked(true);
        upDateAnimation(0);
    } else if(position >= 6 && position < 12){
        bt2.setChecked(true);
        upDateAnimation(1);
    } else if(position >= 12 && position < 18){
        bt3.setChecked(true);
        upDateAnimation(2);
    } else{
        bt4.setChecked(true);
        upDateAnimation(3);
    }
}
在实现viewpager的addOnPageChangeListener监听中添加限制条件,在这里,我的每个按钮中有6个fragment,所以需要限制.

在upDateAnimation中传入点击的按钮的下标.

@Override
public void onTabChecked(int id) {
    switch (id){
        case R.id.rb_one:
            if(bottomView.getCurrentPosition() > 5)
                mViewPager.setCurrentItem(0,false);
            break;
        case R.id.rb_two:
            if(bottomView.getCurrentPosition() < 6 || bottomView.getCurrentPosition() > 11)
                mViewPager.setCurrentItem(6,false);
            break;
        case R.id.rb_three:
            if(bottomView.getCurrentPosition() < 12 || bottomView.getCurrentPosition() > 17) {
                mViewPager.setCurrentItem(12,false);
            }
            break;
        case R.id.rb_four:
            if(bottomView.getCurrentPosition() < 18)
                mViewPager.setCurrentItem(18,false);
            break;
    }
}

相应的,为了保证不会重复计算,在RadioGroup的onCheckedChangeListener中也要添加限制.

到这里,基本上TabLayout的功能就已经是现实了,想要改变横线的长短,只需要改变算法即可.

欢迎指正,共同进步.