欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 中TabLayout自定义选择背景滑块的实例代码

程序员文章站 2024-03-04 15:19:41
 tablayout是android 的material design包中的一个控件,可以和v4包中的viewpager搭配产生一个联动的效果。这里我自定义了一个...

 tablayout是android 的material design包中的一个控件,可以和v4包中的viewpager搭配产生一个联动的效果。这里我自定义了一个滑块能够跟随tablayout进行滑动选择的sliderlayout。效果见下图(白色方框):

Android 中TabLayout自定义选择背景滑块的实例代码

下面是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自定义选择背景滑块的实例代码,希望对大家有所帮助