Android自定义竖直方向SeekBar多色进度条
程序员文章站
2024-03-04 19:17:18
写在前面
因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下:
具体实现
本来想定义水平的...
写在前面
因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下:
具体实现
本来想定义水平的,然后旋转一下,后来发现还不如直接定义竖直方向来的直接,就直接在竖直方向画了下。
首先讲一下思路,就是通过继承view,然后通过ondraw()方法进行绘制。具体绘制的时候,需要处理一些小细节。
比如,我们需要画一个圆形的滑动块,那么我们的背景色带就不能把整个宽度占满,要不然,小圆块只能和色带一样宽了,效果不是很好看,所以在绘制的时候应该把背景画的宽度小于view的实际宽度。
接下来我要贴代码了:
@override protected void ondraw(canvas canvas) { super.ondraw(canvas); int h = getmeasuredheight(); int w = getmeasuredwidth(); mradius = (float) w/2; sleft = w * 0.25f; // 背景左边缘坐标 sright = w * 0.75f;// 背景右边缘坐标 stop = 0; sbottom = h; swidth = sright - sleft; // 背景宽度 sheight = sbottom - stop; // 背景高度 x = (float) w/2;//圆心的x坐标 y = (float) (1-0.01*progress)*sheight;//圆心y坐标 drawbackground(canvas); drawcircle(canvas); paint.reset(); }
再看下画背景:
private void drawbackground(canvas canvas){ rectf rectblackbg = new rectf(sleft, stop, sright, sbottom); lineargradient=new lineargradient(sleft,stop,swidth,sheight,colorarray,null, shader.tilemode.mirror); paint.setantialias(true); paint.setstyle(paint.style.fill); //设置渲染器 paint.setshader(lineargradient); canvas.drawroundrect(rectblackbg, swidth/2, swidth/2, paint); }
这里使用lineargradient实现多种颜色渐变,默认初始化定义如下:
private int endcolor=color.white; private int thumbcolor=color.black; private int thumbbordercolor=color.white; private int colorarray[]={startcolor, middlecolor, endcolor};
然后看下画圆的操作:
private void drawcircle(canvas canvas){ paint thumbpaint = new paint(); y = y < mradius ? mradius : y;//判断thumb边界 y = y > sheight-mradius ? sheight-mradius : y; thumbpaint.setantialias(true); thumbpaint.setstyle(paint.style.fill); thumbpaint.setcolor(thumbcolor); canvas.drawcircle(x, y, mradius, thumbpaint); thumbpaint.setstyle(paint.style.stroke); thumbpaint.setcolor(thumbbordercolor); thumbpaint.setstrokewidth(2); canvas.drawcircle(x, y, mradius, thumbpaint); }
这里通过画布画了一个圆形,内部填充和外边沿。
上面的过程已经可以使效果展示出来了,但是无法操作,我们还需要给它加上事件才行:
@override public boolean ontouchevent(motionevent event) { this.y = event.gety(); progress= (sheight-y)/sheight*100; switch(event.getaction()) { case motionevent.action_down: break; case motionevent.action_up: if (onstatechangelistener!=null){ onstatechangelistener.onstoptrackingtouch(this, progress); } break; case motionevent.action_move: if (onstatechangelistener!=null){ onstatechangelistener.onstatechangelistener(this, progress); } setprogress(progress); this.invalidate(); break; } return true; } public interface onstatechangelistener{ void onstatechangelistener(view view, float progress); void onstoptrackingtouch(view view, float progress); } public void setonstatechangelistener(onstatechangelistener onstatechangelistener){ this.onstatechangelistener=onstatechangelistener; }
这里写了个回调接口,然后我们在activity中就可以接收到相应的滑动进度,进而进行操作,当然,这里我们还得再加一个方法,以便改变seekbar的状态:
public void setprogress(float progress) { this.progress = progress; invalidate(); }
到这里,功能基本就ok了,然后我们可以在activity中去使用它了,下面是布局中的引用:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/bgcolor" > <include layout="@layout/bar_simple_title" /> <linearlayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center" > <relativelayout android:layout_margintop="20dp" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginright="35dp" > <textview android:id="@+id/tv_inner_temper" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/inner_temperature" android:layout_centerhorizontal="true" /> <com.tfxiaozi.widget.verticalcolorseekbar android:id="@+id/vpb_inner_temper" android:layout_width="20dp" android:layout_height="300dp" android:layout_centerhorizontal="true" android:layout_margintop="30dp"/> <textview android:id="@+id/tv_current_temper" android:layout_below="@id/vpb_inner_temper" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/current_temperature" /> </relativelayout> <relativelayout android:layout_marginleft="35dp" android:layout_margintop="20dp" android:layout_width="wrap_content" android:layout_height="match_parent" > <textview android:id="@+id/tv_brightness" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/brightness" android:layout_centerhorizontal="true" /> <com.tfxiaozi.widget.verticalcolorseekbar android:id="@+id/vpb_brightness" android:layout_width="20dp" android:layout_height="300dp" android:layout_centerhorizontal="true" android:layout_margintop="30dp"/> <textview android:id="@+id/tv_current_brightness" android:layout_below="@id/vpb_brightness" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerhorizontal="true" android:text="0" /> </relativelayout> </linearlayout> </linearlayout>
怎么使用就很简单了:
package com.tfxiaozi.activity.setting; import android.graphics.color; import android.os.bundle; import android.view.view; import android.widget.imageview; import android.widget.textview; import com.tfxiaozi.r; import com.tfxiaozi.activity.baseactivity; import com.tfxiaozi.utils.toastutils; import com.tfxiaozi.widget.verticalcolorseekbar; /** * created by dongqiang on 2016/10/16. */ public class manualsettingactivity extends baseactivity implements view.onclicklistener, verticalcolorseekbar.onstatechangelistener { private textview tvcurrenttemper, tvcurrentbrightness, tvmaintitle; private imageview ivback; private verticalcolorseekbar vpbinnertemper; private verticalcolorseekbar vpbbrightness; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_manual_setting); initviews(); initevents(); initdata(); } private void initviews() { tvmaintitle = (textview) findviewbyid(r.id.title_main_text); tvmaintitle.settext(getstring(r.string.manual_setting)); tvmaintitle.setvisibility(view.visible); ivback = (imageview) findviewbyid(r.id.title_back); ivback.setvisibility(view.visible); tvcurrenttemper = (textview) findviewbyid(r.id.tv_current_temper); tvcurrentbrightness = (textview) findviewbyid(r.id.tv_current_brightness); vpbinnertemper = (verticalcolorseekbar)findviewbyid(r.id.vpb_inner_temper); vpbbrightness = (verticalcolorseekbar) findviewbyid(r.id.vpb_brightness); vpbinnertemper.setcolor(color.red, color.yellow, color.green, color.blue, color.transparent); vpbbrightness.setcolor(color.blue, color.white, color.yellow, color.blue, color.transparent); } private void initevents() { ivback.setonclicklistener(this); vpbinnertemper.setonstatechangelistener(this); vpbbrightness.setonstatechangelistener(this); } private void initdata() { vpbinnertemper.setprogress(50); vpbbrightness.setprogress(70); } @override public void onclick(view v) { switch (v.getid()) { case r.id.title_back: finish(); break; } } @override public void onstatechangelistener(view view, float progress) { } @override public void onstoptrackingtouch(view view, float progress) { int viewid = view.getid(); switch (viewid) { case r.id.vpb_inner_temper: if (progress < 0) { progress = 0; } if(progress > 100) { progress = 100; } toastutils.showshort(this, "progress= " + progress); break; case r.id.vpb_brightness: if (progress < 0) { progress = 0; } if(progress > 100) { progress = 100; } toastutils.showshort(this, "progress1= " + progress); break; } } }
到这里就结束了,最后还是附上自定义view的整个代码吧:
package com.tfxiaozi.widget; import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.lineargradient; import android.graphics.paint; import android.graphics.rectf; import android.graphics.shader; import android.util.attributeset; import android.util.log; import android.view.motionevent; import android.view.view; /** * created by dongqiang on 2016/10/21. */ public class verticalcolorseekbar extends view{ private static final string tag = verticalcolorseekbar.class.getsimplename(); private int startcolor= color.black; private int middlecolor = color.gray; private int endcolor=color.white; private int thumbcolor=color.black; private int thumbbordercolor=color.white; private int colorarray[]={startcolor, middlecolor, endcolor}; private float x,y; private float mradius; private float progress; private float maxcount = 100f; private float sleft, stop, sright, sbottom; private float swidth,sheight; private lineargradient lineargradient; private paint paint = new paint(); protected onstatechangelistener onstatechangelistener; public verticalcolorseekbar(context context) { this(context, null); } public verticalcolorseekbar(context context, attributeset attrs) { super(context, attrs); } @override protected synchronized void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); setmeasureddimension(getmeasuredwidth(), getmeasuredheight()); } public void setcolor(int startcolor,int middlecolor, int endcolor,int thumbcolor,int thumbbordercolor){ this.startcolor= startcolor; this.middlecolor = middlecolor; this.endcolor= endcolor; this.thumbcolor= thumbcolor; this.thumbbordercolor= thumbbordercolor; colorarray[0] = startcolor; colorarray[1] = middlecolor; colorarray[2] = endcolor; } @override protected void ondraw(canvas canvas) { super.ondraw(canvas); int h = getmeasuredheight(); int w = getmeasuredwidth(); mradius = (float) w/2; sleft = w * 0.25f; // 背景左边缘坐标 sright = w * 0.75f;// 背景右边缘坐标 stop = 0; sbottom = h; swidth = sright - sleft; // 背景宽度 sheight = sbottom - stop; // 背景高度 x = (float) w/2;//圆心的x坐标 y = (float) (1-0.01*progress)*sheight;//圆心y坐标 drawbackground(canvas); drawcircle(canvas); paint.reset(); } private void drawbackground(canvas canvas){ rectf rectblackbg = new rectf(sleft, stop, sright, sbottom); lineargradient=new lineargradient(sleft,stop,swidth,sheight,colorarray,null, shader.tilemode.mirror); paint.setantialias(true); paint.setstyle(paint.style.fill); //设置渲染器 paint.setshader(lineargradient); canvas.drawroundrect(rectblackbg, swidth/2, swidth/2, paint); } private void drawcircle(canvas canvas){ paint thumbpaint = new paint(); y = y < mradius ? mradius : y;//判断thumb边界 y = y > sheight-mradius ? sheight-mradius : y; thumbpaint.setantialias(true); thumbpaint.setstyle(paint.style.fill); thumbpaint.setcolor(thumbcolor); canvas.drawcircle(x, y, mradius, thumbpaint); thumbpaint.setstyle(paint.style.stroke); thumbpaint.setcolor(thumbbordercolor); thumbpaint.setstrokewidth(2); canvas.drawcircle(x, y, mradius, thumbpaint); } @override public boolean ontouchevent(motionevent event) { this.y = event.gety(); progress= (sheight-y)/sheight*100; switch(event.getaction()) { case motionevent.action_down: break; case motionevent.action_up: if (onstatechangelistener!=null){ onstatechangelistener.onstoptrackingtouch(this, progress); } break; case motionevent.action_move: if (onstatechangelistener!=null){ onstatechangelistener.onstatechangelistener(this, progress); } setprogress(progress); this.invalidate(); break; } return true; } public interface onstatechangelistener{ void onstatechangelistener(view view, float progress); void onstoptrackingtouch(view view, float progress); } public void setonstatechangelistener(onstatechangelistener onstatechangelistener){ this.onstatechangelistener=onstatechangelistener; } public void setprogress(float progress) { this.progress = progress; invalidate(); } }
结束
到这里就真的结束啦,就当记录一下吧,然后也希望帮到有需要的人。有更好的实现也可以告诉我哈~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。