Android自定义TabLayout效果
周末就要到了,今天项目中遇到这样一个tab,选中tab的背景是个圆角矩形,方向指向器没有了,这样普通的tablayout不能满足我的要求,可能会想到动态的去设置选中tab的背景不就可以了,但是那样的话太生硬了,没有动画效果,其实想想也还比较简单,今天就简单的说一说这个yzztab。效果如下图:
这里是四个tab,一版只显示3个,这里假设有num个tab,当滑动到第3个时,这里就需要考虑如何让tablayout和指示器一起移动呢?
@override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { if (positionoffset>1){ return; } int leftcop = (int) (positionoffset*(getmeasuredwidth()/mmaxlinenum)+position*getmeasuredwidth()/mmaxlinenum); if (leftcop!=leftfortablayout){ //这里要做判断是否滑动,当选择的位置大于tablayout中显示的最大数-1时,会向左右滑动,指示器也会 //跟这滑动,相对静止,否则指示器滑动,tab布局不移动 if (position>=mmaxlinenum-1) { scrollcontent += leftcop - leftfortablayout; scrollto(scrollcontent, 0); //这里要重新layout update(); } leftfortablayout = leftcop; invalidate(); } }
首先,在viewpage的监听中,positionoffset有时候可能大于1,这点需要注意的,当两次left的坐标相等 时,我们就不进行绘制了,接下来就是
如何确定left的值了,对于这点我也想了很久,最后终于得出结论:
int leftcop = (int) (positionoffset*(getmeasuredwidth()/mmaxlinenum)+position*getmeasuredwidth()/mmaxlinenum);
因为当positionoffset的值在向右滑动80%左右的时候getcurrentitem()的值会发生变化,这点可以试验一下,所以getcurrentitem()方法不能用了,只能用参数position.layout滑动的实际代码注释很详细了,我就不再阐述了,可以试试。在布局滑动了以后,必须要layout,不然view的属性不会变,点击没法应,但是也可以不更新,动态的告诉用户点击的真是tab,这样也可以。
private void update() { for (int i = 0; i <mchildcount ; i++) { view v = getchildat(i); v.setleft(v.getleft()+scrollcontent); } //必须调用,不然不会重新layout requestlayout(); }
接下来就是绘制了,viewgroup是默认不调用ondraw(canvas canvas)方法的,原因很简单,viewgroup是个容器,主要作用是起承载作用,绘画就交给子view了,但是还是有办法让其调用该方法的,如下:
setwillnotdraw(false);
这就告诉该容器,需要绘制;
接下来就是绘制指向器和选中背景了,一个圆角矩形和一条线,比较简单,我就不再详细说明了。
@override protected void ondraw(canvas canvas) { //left = getmeasuredwidth() / mchildcount * mselectposition; super.ondraw(canvas); mpaint.setcolor(color.green); int top = getmeasuredheight() / 4; int right = leftfortablayout + getmeasuredwidth() / mmaxlinenum; int bottom = getmeasuredheight() - getmeasuredheight() / 4; rectf rectf = new rectf(leftfortablayout, top, right, bottom); mpaint.setantialias(true); mpaint.setstyle(paint.style.fill); canvas.drawroundrect(rectf, 10, 10, mpaint); mpaint.setcolor(color.red); mpaint.setstrokewidth(5); canvas.drawline(leftfortablayout,getmeasuredheight()-5,right,getmeasuredheight()-5,mpaint); }
接下来介绍建与viewpager建立关联的方法
/** * 于viewpager建立联系,这里必须先要给viewpager设置adapter * * @param viewpager */ public void setupwithviewpager(viewpager viewpager) { mviewpager = viewpager; mchildcount = viewpager.getadapter().getcount(); mselectposition = viewpager.getcurrentitem(); viewpager.setonpagechangelistener(this); }
初始化的方法
/** * 为tab添加view */ private void init() { setwillnotdraw(false); mpaint = new paint(); for (int i = 0; i < mchildcount; i++) { final textview tv = new textview(getcontext()); int w = getmeasuredwidth()/mmaxlinenum; linearlayout.layoutparams lp = new layoutparams(w, viewgroup.layoutparams.match_parent); tv.settext("tab" + i); tv.setgravity(gravity.center); tv.setlayoutparams(lp); final int finali = i; tv.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { if (montabselecterlistener != null){ montabselecterlistener.selecter(finali,tv); } } }); addview(tv); } }
这里只是很简单的加了几个textview进去,也可以弄个方法,通过用户动态添加自己想要的view,都可以实现的。至于监听的话就很简单了.上面已经写到了。
yzztab的代码
package a6he.android.yzz.com.mytablayout; import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.rect; import android.graphics.rectf; import android.support.v4.view.viewpager; import android.util.attributeset; import android.util.log; import android.view.gravity; import android.view.view; import android.view.viewgroup; import android.widget.linearlayout; import android.widget.switch; import android.widget.textview; /** * created by yzz on 2017/2/24 0024. * <p/> * 实现背景随着viewpager的滑动跟着移动 */ public class yzztab extends linearlayout implements viewpager.onpagechangelistener { private viewpager mviewpager; private paint mpaint; //tab的数量 private int mchildcount; //tab选中的位置 private int mselectposition; //绘制指向器的左顶点 private int leftfortablayout = 0; private int leftforinvidator = 0; private int mmaxlinenum = 3; private int scrollcontent = 0; private ontabselecterlistener montabselecterlistener; public yzztab(context context) { super(context); } public yzztab(context context, attributeset attrs) { super(context, attrs); } public yzztab(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } @override protected void onfinishinflate() { super.onfinishinflate(); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); init(); } /** * 于viewpager建立联系,这里必须先要给viewpager设置adapter * * @param viewpager */ public void setupwithviewpager(viewpager viewpager) { mviewpager = viewpager; mchildcount = viewpager.getadapter().getcount(); mselectposition = viewpager.getcurrentitem(); viewpager.setonpagechangelistener(this); } /** * 为tab添加view */ private void init() { setwillnotdraw(false); mpaint = new paint(); for (int i = 0; i < mchildcount; i++) { final textview tv = new textview(getcontext()); int w = getmeasuredwidth()/mmaxlinenum; linearlayout.layoutparams lp = new layoutparams(w, viewgroup.layoutparams.match_parent); tv.settext("tab" + i); tv.setgravity(gravity.center); tv.setlayoutparams(lp); final int finali = i; tv.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { if (montabselecterlistener != null){ montabselecterlistener.selecter(finali,tv); } } }); addview(tv); } } @override protected void ondraw(canvas canvas) { //left = getmeasuredwidth() / mchildcount * mselectposition; super.ondraw(canvas); mpaint.setcolor(color.green); int top = getmeasuredheight() / 4; int right = leftfortablayout + getmeasuredwidth() / mmaxlinenum; int bottom = getmeasuredheight() - getmeasuredheight() / 4; rectf rectf = new rectf(leftfortablayout, top, right, bottom); mpaint.setantialias(true); mpaint.setstyle(paint.style.fill); canvas.drawroundrect(rectf, 10, 10, mpaint); mpaint.setcolor(color.red); mpaint.setstrokewidth(5); canvas.drawline(leftfortablayout,getmeasuredheight()-5,right,getmeasuredheight()-5,mpaint); } @override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) { if (positionoffset>1){ return; } int leftcop = (int) (positionoffset*(getmeasuredwidth()/mmaxlinenum)+position*getmeasuredwidth()/mmaxlinenum); if (leftcop!=leftfortablayout){ //这里要做判断是否滑动,当选择的位置大于tablayout中显示的最大数-1时,会向左右滑动,指示器也会 //跟这滑动,相对静止,否则指示器滑动,tab布局不移动 if (position>=mmaxlinenum-1) { scrollcontent += leftcop - leftfortablayout; scrollto(scrollcontent, 0); //这里要重新layout update(); } leftfortablayout = leftcop; invalidate(); } } private void update() { for (int i = 0; i <mchildcount ; i++) { view v = getchildat(i); v.setleft(v.getleft()+scrollcontent); } requestlayout(); } @override public void onpageselected(int position) { } @override public void onpagescrollstatechanged(int state) { switch (state){ } } public void setmmaxlinenum(int mmaxlinenum) { this.mmaxlinenum = mmaxlinenum; } public void setontabselecterlistener(ontabselecterlistener montabselecterlistener) { this.montabselecterlistener = montabselecterlistener; } interface ontabselecterlistener{ void selecter(int position,view view); } }
好啦,就介绍这么多,还有待完善,继续封装,完成更强大的功能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。