Android中利用RadioGroup和View实现TabLayout的
我们知道,在使用tabLayout的时候,其下面的标记线google没有直接提供给我们APi去修改它的长度,那么今天来使用<RadioGroup> 和 <RadioButton> 与 <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的功能就已经是现实了,想要改变横线的长短,只需要改变算法即可.
欢迎指正,共同进步.