TabLayout是Android 的Material Design包中的一个控件,可以和V4包中的ViewPager搭配产生一个联动的效果。这里我自定义了一个滑块能够跟随TabLayout进行滑动选择的SliderLayout。效果见下图(白色方框):

下面是SliderLayout的源码:

import android.content.Context;import android.content.res.TypedArray;import android.graphics.drawable.Drawable;import android.support.design.widget.TabLayout;import android.util.AttributeSet;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import java.lang.ref.WeakReference;/*** Created by yyw on 2016/4/28.* 一个用来显示当前的index的滑块*/public class SliderLayout extends LinearLayout {private int totalNum = 0;private ImageView mSlider;private Drawable mSliderImage;private WeakReference mTabLayoutRef;public SliderLayout(Context context) {this(context, null);}public SliderLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public SliderLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SliderLayout);mSliderImage = array.getDrawable(R.styleable.SliderLayout_slider_pic);if (mSliderImage == null) {mSliderImage = context.getResources().getDrawable(R.drawable.slider);}array.recycle();init(context);}private void init(Context context) {mSlider = new ImageView(context);mSlider.setImageDrawable(mSliderImage);addView(mSlider, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);resetSlider();}/*** 重新设置滑块*/private void resetSlider() {if (getOrientation() == HORIZONTAL) {resetHorizontalSlider();}}/*** 重置水平方向的滑块大小*/private void resetHorizontalSlider() {if (mTabLayoutRef == null) return;TabLayout tabLayout = mTabLayoutRef.get();if (tabLayout == null) return;LinearLayout mTabStrip = (LinearLayout) tabLayout.getChildAt(0);totalNum = mTabStrip.getChildCount();if (totalNum > 0) {View firstView = mTabStrip.getChildAt(0);int width = firstView.getMeasuredWidth();resetSlider(width);}}//重新设置滑块的大小private void resetSlider(int width) {LayoutParams params = (LayoutParams) mSlider.getLayoutParams();params.width = width;//重新设置滑块的大小params.height = getHeight() / 2;params.gravity = Gravity.CENTER_VERTICAL;mSlider.setPadding(width / 10, 0, width / 10, 0);//设置View的左右向内收缩mSlider.setLayoutParams(params);}public void setupWithTabLayout(TabLayout tabLayout) {mTabLayoutRef = new WeakReference<>(tabLayout);resetHorizontalSlider();}public static final String TAG = SliderLayout.class.getName();public static class SliderOnPageChangeListener extends TabLayout.TabLayoutOnPageChangeListener {private final WeakReference mSliderLayoutRef;public SliderOnPageChangeListener(TabLayout tabLayout, SliderLayout layout) {super(tabLayout);mSliderLayoutRef = new WeakReference(layout);layout.setupWithTabLayout(tabLayout);}@Overridepublic void onPageScrollStateChanged(int state) {super.onPageScrollStateChanged(state);}@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {super.onPageScrolled(position, positionOffset, positionOffsetPixels);final SliderLayout layout = mSliderLayoutRef.get();if (layout != null) {layout.setScrollPosition(position, positionOffset);}}}/*** 把滑块滑动到指定的位置** @param position 当前位置* @param positionOffset 滑动到下一个或上一个位置比例*/private void setScrollPosition(int position, float positionOffset) {final int roundedPosition = Math.round(position + positionOffset);if (roundedPosition < 0 || roundedPosition >= totalNum) {return;}float scrollX = calculateScrollXForTab(position, positionOffset);scrollTo((int) scrollX, 0);}/*** 计算滑块需要滑动的距离** @param position 当前选择的位置* @param positionOffset 滑动位置的百分百* @return 滑动的距离*/private int calculateScrollXForTab(int position, float positionOffset) {TabLayout tabLayout = mTabLayoutRef.get();if (tabLayout == null) return 0;LinearLayout mTabStrip = (LinearLayout) tabLayout.getChildAt(0);if (mTabStrip == null) return 0;//当前选择的Viewfinal View selectedChild = mTabStrip.getChildAt(position);//下一个Viewfinal View nextChild = position + 1 < mTabStrip.getChildCount()? mTabStrip.getChildAt(position + 1): null;//当前选择的View的宽度final int selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;//下一个View的宽度final int nextWidth = nextChild != null ? nextChild.getWidth() : 0;//当前选择的View的左边位置,view的方位final int left = selectedChild != null ? selectedChild.getLeft() : 0;//计算滑块需要滑动的距离,左 + ,右 - ;int scrollX = -(left + ((int) ((selectedWidth + nextWidth) * positionOffset * 0.5f)));if (tabLayout.getTabMode() == TabLayout.MODE_SCROLLABLE) {//当为滑动模式的时候TabLayout会有水平方向的滑动scrollX += tabLayout.getScrollX();//计算在TabLayout有滑动的时候,滑块相对的滑动距离}return scrollX;}}

其中比较关键的一个类是SliderOnPageChangeListener 这个类继承的TabLayout.TabLayoutOnPageChangeListener类这个类我们看源码(下面)这个是监听ViewPager滑动选择的一个接口。我们要做的就是在这个类基础上进行扩展让SliderLayout也能监听到ViewPager的滑动。

public static class TabLayoutOnPageChangeListener implements ViewPager.OnPageChangeListener {private final WeakReference mTabLayoutRef;private int mPreviousScrollState;private int mScrollState;public TabLayoutOnPageChangeListener(TabLayout tabLayout) {mTabLayoutRef = new WeakReference<>(tabLayout);}@Overridepublic void onPageScrollStateChanged(int state) {mPreviousScrollState = mScrollState;mScrollState = state;}@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {//省略}}@Overridepublic void onPageSelected(int position) {//省略}private void reset() {mPreviousScrollState = mScrollState = SCROLL_STATE_IDLE;}}

计算每次SliderLayout需要滑动的距离的方法是calculateScrollXForTab(int position, float positionOffset)(详细看源码)根据监听到的ViewPager滑动进行相关的计算并滑动SliderLayout

应用的时候一定要注意viewPager.setOnPageChangeListener(new SliderLayout.SliderOnPageChangeListener(mTabLayout,layout));要在mTabLayout.setupWithViewPager(viewPager);之后调用:

public class MainActivity extends AppCompatActivity {public static final String TAG = MainActivity.class.getName();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final TabLayout mTabLayout = (TabLayout) findViewById(R.id.tab_layout);ViewPager viewPager = (ViewPager) findViewById(R.id.vp);SliderLayout layout = (SliderLayout) findViewById(R.id.slider_layout);viewPager.setAdapter(new MViewPagerAdapter(getSupportFragmentManager()));mTabLayout.setupWithViewPager(viewPager);//方法一定要在mTabLayout.setupWithViewPager(viewPager)之后不然没有效果viewPager.setOnPageChangeListener(new SliderLayout.SliderOnPageChangeListener(mTabLayout,layout));}class MViewPagerAdapter extends FragmentPagerAdapter {public final String[] names = new String[]{"音乐","电影","电视","综艺","直播","音乐","电影","电视","综艺","直播"};public MViewPagerAdapter(FragmentManager fm) {super(fm);}@Overridepublic Fragment getItem(int position) {return BlankFragment.newInstance("param1", "param2");}@Overridepublic int getCount() {return 10;}@Overridepublic CharSequence getPageTitle(int position) {return names[position];}}}

布局:

<?xml version="1.0" encoding="utf-8"?><?xml version="1.0" encoding="utf-8"?>

以上所述是小编给大家介绍的Android 中TabLayout自定义选择背景滑块的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

更多相关文章

  1. Android第三方文件选择器aFileChooser使用方法详解
  2. 实现Android多张图片选择
  3. Android’s HTTP Clients--Android(安卓)HTTP 客户端选择
  4. Mac版 Android(安卓)studio 快捷键(Keymap-Eclise Mac OS X)
  5. 自定义View详解
  6. Intellij Idea12第一个安卓程序开发(HelloWorld)及简单讲解Android
  7. ViewPager两大弊端优化方案
  8. Android两行代码搞定ViewPager的过渡动画
  9. Android(安卓)ListView多选模式

随机推荐

  1. Android 10ms问题:关于Android音频路径延
  2. Android配置QQ邮箱问题
  3. 简单的android客户端servlet服务端的交互
  4. 《淘宝客户端 for Android》项目实战 htm
  5. Android实现透明的颜色效果
  6. 三十三、Android给ListView设置分割线Div
  7. Android 5.0 默认水波纹背景属性,可设置
  8. android在RelativeLayout里的TextView或
  9. 利用oom_adj提高Application所在进程的优
  10. 丰富多彩的Android onTouch事件