当前位置: 移动技术网 > IT编程>移动开发>Android > Android自定义竖直方向SeekBar多色进度条

Android自定义竖直方向SeekBar多色进度条

2019年07月24日  | 移动技术网IT编程  | 我要评论

二垒都没挂上,今日船期网,风云直播浙江卫视

写在前面

因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下:

具体实现

本来想定义水平的,然后旋转一下,后来发现还不如直接定义竖直方向来的直接,就直接在竖直方向画了下。

首先讲一下思路,就是通过继承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();
 }
}

结束

到这里就真的结束啦,就当记录一下吧,然后也希望帮到有需要的人。有更好的实现也可以告诉我哈~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网