Android之SeekBar(0在中间)

本文主要记录一些零碎的东西

公司UI想出一个SeekBar,中间是0 ,往左是负的,往右是正的,自带的完全无法满足,只能自己撸了,想了一下,有些思路

主要是Canvas 类画直线,画圆,画圆角矩形,看看效果


效果看着还可以,因为要支持最左边的点是0,所以设置了两种模式的切换,

跟随手势移动的处理:
touch事件,判断touch点是否在Thumb上,如果是在拉动圆点

/**
     * 判断是否 touch 在 seekBar thumb 上
     *
     * @param event
     * @return
     */
    private boolean isTouchingTarget(MotionEvent event) {
        isTouchLegal = event.getRawX() > progressPosition - DEFAULT_TOUCH_TARGET_SIZE
                && event.getRawX() < progressPosition + DEFAULT_TOUCH_TARGET_SIZE;
//        Log.i("slack", "isTouchLegal " + isTouchLegal);
        return isTouchLegal;
    }

根据手在屏幕上的位置以及该View的布局(宽度高度)计算出当前的progress
/**
     * return  progress
     * -maxProgress          minProgress              maxProgress
     * \------------------------0---------------------------\
     * min                   center     touch-->\          max
     * (min center touch max are positions in the screen)
     * touch progress = (touch - center) / (max - center) * maxProgress;
     */
    private float clamp(int value) {
        if (mIsCenterState) {
            int centerX = getWidth() / 2;
            float min = centerX - width / 2;// the start point
            float max = centerX + width / 2;// the end point
            if (value > centerX) {
                if (value >= max) {
                    return maxProgress;
                } else {
                    return (int) ((maxProgress - minProgress) * (value - centerX) / (width / 2f));
                }
            } else if (value < centerX) {
                if (value <= min) {
                    return -maxProgress;
                } else {
                    return (int) ((maxProgress - minProgress) * (value - centerX) / (width / 2f));
                }
            } else {
                return minProgress;
            }
        } else {
            int centerX = getWidth() / 2;
            float min = centerX - width / 2;// the start point
            float max = centerX + width / 2;// the end point
            if (value >= max) {
                return maxProgress;
            } else if (value <= min) {
                return minProgress;
            } else {
                return (maxProgress - minProgress) * (value - min) / width ;
            }
        }
    }
移动时增加自定义动画
/**
     * 自定义动画  ofFloat(Object target, String propertyName, float... values)
     * 第一个参数用于指定这个动画要操作的是哪个控件
     * 第二个参数用于指定这个动画要操作这个控件的哪个属性
     * 第三个参数是可变长参数,这个就跟ValueAnimator中的可变长参数的意义一样了,就是指这个属性值是从哪变到哪
     * 对于自定义的属性,d第二个参数需要提供setXXX 方法,like:  public void setMThumbRadius(int mThumbRadius)
     * set方法 属性的第一个字母记得要大写 !  ObjectAnimator.ofInt , ofInt 对应参数的类型,如果float 为ofFloat
     */
    private ObjectAnimator getTargetAnimator(boolean touching) {
        final ObjectAnimator anim = ObjectAnimator.ofFloat(this,
                "mThumbRadius",
                mThumbRadius,
                touching ? mThumbPressedRadius : mThumbNormalRadius);
        anim.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
//                Log.i("slack","onAnimationUpdate...");
                postInvalidate(); // 在子线程中使用刷新View
            }
        });
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
//                Log.i("slack","onAnimationEnd...");
                anim.removeAllListeners();
            }
        });
        anim.setInterpolator(new AccelerateInterpolator());
        return anim;
    }

    public void setMThumbRadius(float mThumbRadius) {
//        Log.i("slack","setmThumbRadius...");
        this.mThumbRadius = mThumbRadius;
    }

看看完整代码 com.cl.slack.seekbar.CenterSeekBar
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;

/**
 * 从中间可以向两边滑动 左负右正
 * Created by slack on 2016/12/12 19:00.
 */

public class CenterSeekBar extends View {

    private static final int DEFAULT_TOUCH_TARGET_SIZE = 40;
    private final int DEFAULT_TEXT_PADDING = 10;

    private Paint paint;

    private float width = 800; // need <= getWidth()

    /**
     * progress start max
     */
    private int minProgress = 0;

    /**
     * progress end max
     */
    private int maxProgress = 100;

    /**
     * 进度条的颜色 底色 背景色
     */
    @ColorInt
    private int progressBackColor = Color.BLACK;

    /**
     * 进度条的底色 高度
     */
    private float progressBackHeight = 10;

    /**
     * 进度条 底色 圆角矩形边框 描边
     */
    @ColorInt
    private int progressFrameColor = Color.WHITE;

    /**
     * 进度条圆角矩形边框 高度
     */
    private float progressFrameHeight = 3;

    /**
     * 进度条的颜色
     */
    @ColorInt
    private int progressColor = Color.GREEN;

    /**
     * 进度条的 高度
     */
    private float progressHeight = 20;

    /**
     * 如果0在中间,负进度条的颜色
     */
    @ColorInt
    private int progressMinusColor = Color.RED;

    /**
     * current progress
     */
    private int progress = 50;

    /**
     * seekBar Thumb normal radius
     */
    private float mThumbNormalRadius = 14;

    /**
     * seekBar Thumb radius when touched
     */
    private float mThumbPressedRadius = 24;

    /**
     * seekBar Thumb color
     */
    @ColorInt
    private int mThumbColor = Color.BLUE;

    /**
     * progress 字体大小
     */
    private float mTextSize = 40;

    /**
     * progress 字体 color
     */
    @ColorInt
    private int mTextColor = Color.WHITE;

    /**
     * progress 字体 背景 color
     */
    @ColorInt
    private int mTextBackColor = 0x7DD2D3D4;

    /**
     * progress 字体 背景 radius
     */
    private float mTextBackRadius = 10;

    /**
     * 判断是否是 0 在中间
     */
    private boolean mIsCenterState = false;

    private float mThumbRadius = mThumbNormalRadius;
    private float progressPosition;
    private boolean isTouchLegal = false;
    private ObjectAnimator mAnimator; //  seekBar Thumb Animator
    private RectF mTextRectF,mBackRectF,mProgressRectF;

    private OnSeekBarProgressListener mOnSeekBarProgressListener;
    private OnSeekBarFinishedListener mOnSeekBarFinishedListener;

    public CenterSeekBar(Context context) {
        this(context, null);
    }

    public CenterSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CenterSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        paint = new Paint();

        if (attrs != null) {
            TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs,
                    R.styleable.CenterSeekBar, 0, 0);
            maxProgress = styledAttrs.getInteger(R.styleable.CenterSeekBar_maxProgress,100);
            minProgress = styledAttrs.getInteger(R.styleable.CenterSeekBar_minProgress,0);
            width = styledAttrs.getDimension(R.styleable.CenterSeekBar_width,800);
            mIsCenterState = styledAttrs
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值