Android自定义滑动进度条

一、效果图

在这里插入图片描述

二、实现过程

实现过程很简单,只要自定义一个TextView,在onTouchEvent中的移动事件中不断重新绘制即可。
为了方便使用,首先自定义几个属性。

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="SlideView">
        <attr name="selectColor" format="color"></attr>
        <attr name="radius" format="dimension"></attr>
        <attr name="maxValue" format="integer"></attr>
    </declare-styleable>
</resources>

初始化代码,主要用到TypedArray来获取设置的值。

public class SlideView extends CenterTextView {
    private  float mCurrentValue;
    private Paint mSelectPaint;
    private int mRadius=100;
    private int mSelectColor;

    private  int mAnimatorDuration=500;

    private  int mMaxValue =20;

    public SlideView(Context context) {
        this(context,null);

    }

    public SlideView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);

    }

    public SlideView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlideView);
        mRadius =(int) ta.getDimension(R.styleable.SlideView_radius,100);
        mSelectColor=ta.getColor(R.styleable.SlideView_selectColor,Color.parseColor("#F5F5F5"));
        mMaxValue=ta.getInt(R.styleable.SlideView_maxValue,100);
        ta.recycle();
        init();
    }

    @Override
    public void init() {
        super.init();
        mSelectPaint = new Paint();
        mSelectPaint.setColor(mSelectColor);

    }
}

触摸事件,当手指在范围时,记录x值,会在onDraw中绘制。

  @Override
  public boolean onTouchEvent(MotionEvent event) {
      if (event.getAction() == MotionEvent.ACTION_MOVE || event.getAction()==MotionEvent.ACTION_UP) {
          if (event.getX()>0 && event.getX()<=getWidth())
          mCurrentValue = ((int) event.getX());
      }
          invalidate();
      return true;
  }

视图绘制,由于是继承TextView,可直接借助background属性来设置背景,就不需要做额外的工作。然后通过drawRect来绘制滑动的大小。也就是鼠标移到哪里,绘制到哪里。

  @Override
  protected void onDraw(Canvas canvas) {
      canvas.drawRect(0, 0, mCurrentValue, getMeasuredHeight(),  mSelectPaint);
      setText(converXToValue(mCurrentValue)+"");
      super.onDraw(canvas);
  }
   private  int   converXToValue(float x){
       return  Math.round(x/getWidth()*mMaxValue) ;
  }

当通过setCurrentValue设置当前值的时候,增加一个动画,显的不那么死板。要注意不能超出最大值。
给ValueAnimator添加AnimatorUpdateListener监听,不断调用invalidate()重新绘制即可。

public void  setCurrentValue(int value){
    if (value>mMaxValue){return;}
    float oldX =mCurrentValue;
    float newX =value*getWidth()/mMaxValue;
    ValueAnimator animator =ValueAnimator.ofFloat(oldX,newX);
    animator.setDuration(mAnimatorDuration);
    animator.setInterpolator(new OvershootInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float v =(float)animation.getAnimatedValue();
            mCurrentValue= v;
            invalidate();
        }
    });
    animator.start();
}

当然还有圆角问题,可以通过以下代码轻松实现。

@Override
public void draw(Canvas canvas) {
    Path path = new Path();
    path.addRoundRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mRadius, mRadius, Path.Direction.CW);
    canvas.clipPath(path);
    super.draw(canvas);
}

使用方法。

<com.hxl.course.widget.SlideView
    android:background="#E76A6A"
    app:selectColor="@color/colorPrimary"
    app:radius="100dp"
    app:maxValue="200"
    android:id="@+id/slideview"
    android:layout_width="match_parent"
    android:layout_height="40dp"></com.hxl.course.widget.SlideView>

完整代码。

package com.hxl.course.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.OvershootInterpolator;

import androidx.annotation.Nullable;

import com.hxl.course.R;

public class SlideView extends CenterTextView {
    private  float mCurrentValue;
    private Paint mSelectPaint;
    private int mRadius=100;
    private int mSelectColor;

    private  int mAnimatorDuration=500;

    private  int mMaxValue =20;

    public SlideView(Context context) {
        this(context,null);

    }

    public SlideView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);

    }



    public SlideView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlideView);
        mRadius =(int) ta.getDimension(R.styleable.SlideView_radius,100);
        mSelectColor=ta.getColor(R.styleable.SlideView_selectColor,Color.parseColor("#F5F5F5"));
        mMaxValue=ta.getInt(R.styleable.SlideView_maxValue,100);
        ta.recycle();
        init();
    }

    @Override
    public void init() {
        super.init();
        mSelectPaint = new Paint();
        mSelectPaint.setColor(mSelectColor);

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_MOVE || event.getAction()==MotionEvent.ACTION_UP) {
            if (event.getX()>0 && event.getX()<=getWidth())
            mCurrentValue = ((int) event.getX());

        }
            invalidate();
        return true;
    }

    @Override
    public void draw(Canvas canvas) {

        Path path = new Path();
        path.addRoundRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mRadius, mRadius, Path.Direction.CW);
        canvas.clipPath(path);
        super.draw(canvas);

    }

    public  int getCurrentValue() {
        return Math.round(mCurrentValue/getWidth()*mMaxValue);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRect(0, 0, mCurrentValue, getMeasuredHeight(),  mSelectPaint);
        setText(converXToValue(mCurrentValue)+"");
        super.onDraw(canvas);

    }

    private  int   converXToValue(float x){
        return  Math.round(x/getWidth()*mMaxValue) ;
    }
    public void  setCurrentValue(int value){
        if (value>mMaxValue){return;}
        float oldX =mCurrentValue;
        float newX =value*getWidth()/mMaxValue;
        ValueAnimator animator =ValueAnimator.ofFloat(oldX,newX);
        animator.setDuration(mAnimatorDuration);
        animator.setInterpolator(new OvershootInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float v =(float)animation.getAnimatedValue();
                mCurrentValue= v;
                invalidate();
            }
        });
        animator.start();

    }

    public void setRadius(int radius) {
        mRadius = radius;
        invalidate();
    }

    public void setAnimatorDuration(int animatorDuration) {
        mAnimatorDuration = animatorDuration;
    }
}

发布了49 篇原创文章 · 获赞 9 · 访问量 8633

猜你喜欢

转载自blog.csdn.net/HouXinLin_CSDN/article/details/104818114
今日推荐