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

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

程序员文章站 2024-03-04 19:17:18
写在前面 因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下: 具体实现 本来想定义水平的...

写在前面

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

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

具体实现

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

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

结束

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

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