当前位置: 首页 > 编程笔记 >

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

诸正谊
2023-03-14
本文向大家介绍Android自定义竖直方向SeekBar多色进度条,包括了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();
 }
}

结束

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

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

 类似资料:
  • 本文向大家介绍Android自定义垂直拖动seekbar进度条,包括了Android自定义垂直拖动seekbar进度条的使用技巧和注意事项,需要的朋友参考一下 Android自带的SeekBar是水平的,要垂直的,必须自己写一个类,继承SeekBar。 一个简单的垂直SeekBar的例子: (但是它其实是存在一些问题的。不过要是满足基本需要还是可以凑合的) Demo中加上一个水平SeekBar作为

  • 本文向大家介绍Android 可拖动的seekbar自定义进度值,包括了Android 可拖动的seekbar自定义进度值的使用技巧和注意事项,需要的朋友参考一下 最近接了个项目其中有需要要实现此功能:seekbar需要显示最左和最右值,进度要跟随进度块移动。下面通过此图给大家展示下效果,可能比文字描述要更清晰。 其实实现起来很简单,主要是思路。自定义控件的话也不难,之前我的博客也有专门介绍,这里

  • 本文向大家介绍Android自定义SeekBar实现视频播放进度条,包括了Android自定义SeekBar实现视频播放进度条的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Android实现视频播放进度条的具体代码,供大家参考,具体内容如下 首先来看一下效果图,如下所示: 其中进度条如下: 接下来说一说我的思路,上面的进度拖动条有自定义的Thumb,在Thumb正上方有一个Popu

  • 本文向大家介绍Android编程自定义进度条颜色的方法详解,包括了Android编程自定义进度条颜色的方法详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android编程自定义进度条颜色的方法。分享给大家供大家参考,具体如下: 先看效果图: 老是提些各种需求问题,我觉得系统默认的颜色挺好的,但是Pk不过,谁叫我们不是需求人员呢,改吧! 这个没法了只能看源码了,还好下载了源码, sou

  • 本文向大家介绍Android编程实现自定义进度条颜色的方法,包括了Android编程实现自定义进度条颜色的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android编程实现自定义进度条颜色的方法。分享给大家供大家参考,具体如下: android 自定义进度条颜色 先看图 基于产品经理各种自定义需求,经过查阅了解,下面是自己对android自定义进度条的学习过程! 这个没法了只能看源

  • 有人能帮我创建balow图像剪切搜索栏吗?我已经用自定义拇指和分段文本浏览过SeekBar,还有SeekBar拇指位置问题 但是我没有成功创建我的客户搜索栏,请帮助我