Android 中TabLayout自定义选择背景滑块的实例代码
程序员文章站
2024-03-04 15:19:41
tablayout是android 的material design包中的一个控件,可以和v4包中的viewpager搭配产生一个联动的效果。这里我自定义了一个...
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<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); } @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<sliderlayout> msliderlayoutref; public slideronpagechangelistener(tablayout tablayout, sliderlayout layout) { super(tablayout); msliderlayoutref = new weakreference<sliderlayout>(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 < 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<tablayout> mtablayoutref; 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]; } } }
布局:
<?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"> <framelayout android:layout_width="match_parent" android:background="@color/cardview_dark_background" android:layout_height="50dp"> <com.example.yyw.waterripple.sliderlayout android: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.tablayout android: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.viewpager android: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"> <corners android:topleftradius="10dp" android:toprightradius="10dp" android:bottomleftradius="10dp" android:bottomrightradius="10dp" /> <solid android:color="#ffffff" /> </shape>
以上所述是小编给大家介绍的android 中tablayout自定义选择背景滑块的实例代码,希望对大家有所帮助
推荐阅读
-
Android 中TabLayout自定义选择背景滑块的实例代码
-
Android 中TabLayout自定义选择背景滑块的实例代码
-
Android中的Button自定义点击效果实例代码
-
Android 中TeaPickerView数据级联选择器功能的实例代码
-
Android中自定义对话框(Dialog)的实例代码
-
Android中的Button自定义点击效果实例代码
-
Android 中TeaPickerView数据级联选择器功能的实例代码
-
Android中自定义对话框(Dialog)的实例代码
-
CSS3中background-size实现背景图片大小可自定义的几种效果(代码实例 )
-
CSS3中background-size实现背景图片大小可自定义的几种效果(代码实例 )