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 WeakReferencemTabLayoutRef; 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); } @Override protected 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); } @Override public void onPageScrollStateChanged(int state) { super.onPageScrollStateChanged(state); } @Override public 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; //当前选择的View final View selectedChild = mTabStrip.getChildAt(position); //下一个View final View nextChild = position + 1
其中比较关键的一个类是SliderOnPageChangeListener 这个类继承的TabLayout.TabLayoutOnPageChangeListener类这个类我们看源码(下面)这个是监听ViewPager滑动选择的一个接口。我们要做的就是在这个类基础上进行扩展让SliderLayout也能监听到ViewPager的滑动。
public static class TabLayoutOnPageChangeListener implements ViewPager.OnPageChangeListener { private final WeakReferencemTabLayoutRef; private int mPreviousScrollState; private int mScrollState; public TabLayoutOnPageChangeListener(TabLayout tabLayout) { mTabLayoutRef = new WeakReference<>(tabLayout); } @Override public void onPageScrollStateChanged(int state) { mPreviousScrollState = mScrollState; mScrollState = state; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { //省略 } } @Override public 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(); @Override protected 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); } @Override public Fragment getItem(int position) { return BlankFragment.newInstance("param1", "param2"); } @Override public int getCount() { return 10; } @Override public CharSequence getPageTitle(int position) { return names[position]; } } }
布局:
<&#63;xml version="1.0" encoding="utf-8"&#63;><&#63;xml version="1.0" encoding="utf-8"&#63;>
以上所述是小编给大家介绍的Android 中TabLayout自定义选择背景滑块的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!