广告
返回顶部
首页 > 资讯 > 移动开发 >Android自定义竖直方向SeekBar多色进度条
  • 149
分享到

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

进度条seekbarAndroid 2022-06-06 07:06:40 149人浏览 独家记忆
摘要

写在前面 因为有这样的一个场景,需要实现竖直方向的多色进度条,然后在网上也找了下,没看到符合需要的,于是自定义了一个,效果如下: 具体实现 本来想定义水平的,然后旋转一下

写在前面

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

具体实现

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

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

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;

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详解及简单实例Android自定义SeekBar实现视频播放进度条Android控件之SeekBar的用法总结Android控件SeekBar仿淘宝滑动验证效果Android 动态改变SeekBar进度条颜色与滑块颜色的实例代码android之SeekBar控件用法详解Android自定义SeekBar滑动显示数字Android关于SeekBar无法点击到最大值问题解决方法记录(推荐)


--结束END--

本文标题: Android自定义竖直方向SeekBar多色进度条

本文链接: https://www.lsjlt.com/news/23613.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作