TabLayout是Android 的Material Design包中的一個控件,可以和V4包中的ViewPager搭配產(chǎn)生一個聯(lián)動的效果。這里我自定義了一個滑塊能夠跟隨TabLayout進(jìn)行滑動選擇的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.* 一個用來顯示當(dāng)前的index的滑塊*/public class SliderLayout extends LinearLayout {private int totalNum = 0;private ImageView mSlider;private Drawable mSliderImage;private WeakReference<TabLayout> 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();}/*** 重新設(shè)置滑塊*/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);}}//重新設(shè)置滑塊的大小private void resetSlider(int width) {LayoutParams params = (LayoutParams) mSlider.getLayoutParams();params.width = width;//重新設(shè)置滑塊的大小params.height = getHeight() / 2;params.gravity = Gravity.CENTER_VERTICAL;mSlider.setPadding(width / 10, 0, width / 10, 0);//設(shè)置View的左右向內(nèi)收縮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<SliderLayout> mSliderLayoutRef;public SliderOnPageChangeListener(TabLayout tabLayout, SliderLayout layout) {super(tabLayout);mSliderLayoutRef = new WeakReference<SliderLayout>(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 當(dāng)前位置* @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);}/*** 計(jì)算滑塊需要滑動的距離** @param position 當(dāng)前選擇的位置* @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;//當(dāng)前選擇的Viewfinal View selectedChild = mTabStrip.getChildAt(position);//下一個Viewfinal View nextChild = position + 1 < mTabStrip.getChildCount()? mTabStrip.getChildAt(position + 1): null;//當(dāng)前選擇的View的寬度final int selectedWidth = selectedChild != null ? selectedChild.getWidth() : 0;//下一個View的寬度final int nextWidth = nextChild != null ? nextChild.getWidth() : 0;//當(dāng)前選擇的View的左邊位置,view的方位final int left = selectedChild != null ? selectedChild.getLeft() : 0;//計(jì)算滑塊需要滑動的距離,左 + ,右 - ;int scrollX = -(left + ((int) ((selectedWidth + nextWidth) * positionOffset * 0.5f)));if (tabLayout.getTabMode() == TabLayout.MODE_SCROLLABLE) {//當(dāng)為滑動模式的時(shí)候TabLayout會有水平方向的滑動scrollX += tabLayout.getScrollX();//計(jì)算在TabLayout有滑動的時(shí)候,滑塊相對的滑動距離}return scrollX;}}其中比較關(guān)鍵的一個類是SliderOnPageChangeListener 這個類繼承的TabLayout.TabLayoutOnPageChangeListener類這個類我們看源碼(下面)這個是監(jiān)聽ViewPager滑動選擇的一個接口。我們要做的就是在這個類基礎(chǔ)上進(jìn)行擴(kuò)展讓SliderLayout也能監(jiān)聽到ViewPager的滑動。
public static class TabLayoutOnPageChangeListener implements ViewPager.OnPageChangeListener {private final WeakReference<TabLayout> 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;}}計(jì)算每次SliderLayout需要滑動的距離的方法是calculateScrollXForTab(int position, float positionOffset)(詳細(xì)看源碼)根據(jù)監(jiān)聽到的ViewPager滑動進(jìn)行相關(guān)的計(jì)算并滑動SliderLayout
應(yīng)用的時(shí)候一定要注意viewPager.setOnPageChangeListener(new SliderLayout.SliderOnPageChangeListener(mTabLayout,layout));要在mTabLayout.setupWithViewPager(viewPager);之后調(diào)用:
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"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><FrameLayoutandroid:layout_width="match_parent"android:background="@color/cardview_dark_background"android:layout_height="50dp"><com.example.yyw.waterripple.SliderLayoutandroid:id="@+id/slider_layout"android:layout_width="match_parent"android:layout_height="50dp"app:slider_pic="@drawable/slider"android:orientation="horizontal" /><android.support.design.widget.TabLayoutandroid:id="@+id/tab_layout"android:layout_width="match_parent"android:layout_height="50dp"app:tabGravity="center"app:tabMode="scrollable"app:tabSelectedTextColor="#ff0000"app:tabTextColor="#ffffff" /></FrameLayout><android.support.v4.view.ViewPagerandroid:id="@+id/vp"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout><declare-styleable name="SliderLayout"><attr name="slider_pic" format="reference" /></declare-styleable><?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><cornersandroid:topLeftRadius="10dp"android:topRightRadius="10dp"android:bottomLeftRadius="10dp"android:bottomRightRadius="10dp" /><solid android:color="#ffffff" /></shape>
以上所述是小編給大家介紹的Android 中TabLayout自定義選擇背景滑塊的實(shí)例代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時(shí)回復(fù)大家的。在此也非常感謝大家對武林網(wǎng)網(wǎng)站的支持!
新聞熱點(diǎn)
疑難解答
圖片精選