可以滑动定值的控件,尺寸工具类

需要的工具类:

1.SizeUtil.java

import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

/**
 * 尺寸相关工具类
 * 1.dpi转px
 * 2.px转dp
 * 3.sp转px
 * 4.px转sp
 * 5.onCreate中强行获取View的宽高
 * 6.获取屏幕的宽度px
 * 7.获取屏幕的高度px
 * 8.获取状态栏高度
 * 9.获取状态栏高度+标题栏(ActionBar)高度
 */

public class SizeUtil {
    //dpi转px
    public static float Dp2Px(Context context, float dpi) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpi, context.getResources().getDisplayMetrics());
    }

    //px转dp
    public static float Px2Dp(Context context, float px) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, context.getResources().getDisplayMetrics());
    }

    //sp转px
    public static float Sp2Px(Context context, float sp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics());
    }

    //px转sp  代码中设置字体大小时这个
    public static float Px2Sp(Context context, float px) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, context.getResources().getDisplayMetrics());
    }

    //onCreate中强行获取View的宽高
    public static int[] forceGetViewSize(View view) {
        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(widthMeasureSpec, heightMeasureSpec);
        return new int[]{widthMeasureSpec, heightMeasureSpec};
    }

    //获取屏幕的宽度px
    public static int getDeviceWidth(Context context) {
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸
        windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高
        return outMetrics.widthPixels;
    }

    //获取屏幕的高度px
    public static int getDeviceHeight(Context context) {
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();// 创建了一张白纸
        windowManager.getDefaultDisplay().getMetrics(outMetrics);// 给白纸设置宽高
        return outMetrics.heightPixels;
    }

    //获取状态栏高度
    public int getStatusBarHeight(Context context) {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    //获取状态栏高度+标题栏(ActionBar)高度
    public static int getTopBarHeight(Activity activity) {
        return activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
    }
}

2.RangeEntity.java

/**
 * 范围选择的实体类
 */
public class RangeEntity {
    private String mTitle;
    private Object mValue;

    public RangeEntity(String title, int value) {
        mTitle = title;
        mValue = value;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public Object getValue() {
        return mValue;
    }

    public void setValue(int value) {
        mValue = value;
    }
}

3.范围值的改变监听 OnRangeChangedListener

/**
 * 选择值范围的滑动监听
 */
public interface OnRangeChangedListener {
    void selected(int start, int end);
}

4.自定义类:RangeBar

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * 滑动定范围值
 */
public class RangeBar extends View {
    
    private int mHeight = 0; // 组件高度
    private int mWidth = 0; // 组件宽度
    
    /**
     * 圆形的半径
     */
    private int mCircleRadius;
    
    /**
     * 线条的颜色
     */
    private int mLineColor;
    
    /**
     * 选中圆形的颜色
     */
    private int mCenterColor;
    private Paint mPaint;
    private int mTextSize; //文字大小
    private float mSingleWidth = 0; //每个刻度的宽度
    private OnRangeChangedListener mListener;
    private float mStartX; //起始点坐标
    private float mEndX; //终止点坐标

    private int mBeginValue = 0; // 计数开始的值
    private int mFinishValue = 0; // 计数结束的值

    private int mStartValue = 0; //开始的值
    private int mEndValue = 0; //结束的值
    private String mIndex = ""; //后缀

    private float mStartProgress = 0; //开始的进度
    private float mEndProgress = 0; // 结束的进度

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

    public RangeBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    //设置后缀
    public void setIndex(String index) {
        mIndex = index;
    }

    //设置起始值
    public void setBeginValue(int beginValue) {
        mBeginValue = beginValue;
        mStartValue = mBeginValue;
        mStartProgress = 0;
    }

    //设置结束值
    public void setFinishValue(int finishValue) {
        mFinishValue = finishValue;
        mEndValue = mFinishValue;
        mEndProgress = 1.0f;
    }

    //设置开始的初始值
    public void setInitValue(int startValue, int endValue) {
        mStartValue = startValue;
        mStartProgress = (mStartValue - mBeginValue) * 1.0f / (mFinishValue - mBeginValue);
        mEndValue = endValue;
        mEndProgress = (mEndValue - mBeginValue) * 1.0f / (mFinishValue - mBeginValue);
        getRightPosition();
    }

    //根据百分比计算开始的坐标和结束的坐标
    private void getRightPosition() {
        mStartX = mCircleRadius * 2 + ((int) (mStartProgress * 100)) * mSingleWidth; //起点坐标
        mEndX = mCircleRadius * 2 + ((int) (mEndProgress * 100)) * mSingleWidth;
        invalidate();
    }

    //设置范围监听器
    public void setRangeChangeListener(OnRangeChangedListener listener) {
        mListener = listener;
    }


    private void init() {
        mCircleRadius = (int) SizeUtil.Dp2Px(getContext(), 10);//圆形的半径
        mCenterColor = getResources().getColor(R.color.colorPoint);//圆形的颜色
        mLineColor = getResources().getColor(R.color.splitGrayColor);//线条的颜色
        mTextSize = (int) SizeUtil.Sp2Px(getContext(), 15);
        mPaint = new Paint();
        mPaint.setDither(true);
        mPaint.setAntiAlias(true);
    }

    private boolean isStartMoving = false;
    private boolean isEndMoving = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        float x = event.getX();
        float y = event.getY();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if ((Math.abs(mStartX - mCircleRadius - x) <= mCircleRadius)) {
                    isStartMoving = true;
                    break;
                }
                if ((Math.abs(mEndX + mCircleRadius - x) <= mCircleRadius)) {
                    isEndMoving = true;
                    break;
                }
                break;
            case MotionEvent.ACTION_UP:
                isStartMoving = false;
                isEndMoving = false;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isStartMoving) {
                    mStartX = x;
                    if (mStartX >= mEndX - mSingleWidth) {
                        mStartX = mEndX - mSingleWidth;
                        Log.i("SingleWidth", mSingleWidth + "");
                    }
                    if (mStartX - mCircleRadius * 2 < 0) {
                        mStartX = mCircleRadius * 2;
                    }
                    Log.i("StartX", mStartX + "");

                }
                if (isEndMoving) {
                    mEndX = x;
                    if (mEndX < mStartX + mSingleWidth) {
                        mEndX = mStartX + mSingleWidth;
                    }
                    if (mEndX + mCircleRadius * 2 > mWidth) {
                        mEndX = mWidth - mCircleRadius * 2;
                    }
                    Log.i("EndX", mEndX + "");

                }
                getRightValue();//获取正确的值
                invalidate();
                break;
        }

        return true;
    }

    //根据坐标获取正确的值
    public void getRightValue() {
        getRightProgress();
        mStartValue = (int) (mBeginValue + (mFinishValue - mBeginValue) * mStartProgress);
        mEndValue = (int) (mBeginValue + (mFinishValue - mBeginValue) * mEndProgress);
        if (mStartValue == mEndValue) {
            if (isStartMoving) {
                mStartValue -= 1;
            } else if (isEndMoving) {
                mEndValue += 1;
            }
        }
        Log.i("Value", mStartValue + ":" + mEndValue);
    }

    //根据坐标获取正确的进度
    public void getRightProgress() {
        mStartProgress = (mStartX - 2 * mCircleRadius) * 1.0f / mSingleWidth / 100;
        mEndProgress = (mEndX - 2 * mCircleRadius) * 1.0f / mSingleWidth / 100;
        Log.i("Progress", mStartProgress + ":" + mEndProgress);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = (int) (SizeUtil.Dp2Px(getContext(), 30) + getPaddingTop() + getPaddingBottom());
        setMeasuredDimension(mWidth, mHeight);
        mSingleWidth = ((mWidth * 1.0f - 4 * mCircleRadius) / 100); //每一个刻度的宽度
        getRightPosition();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制圆角矩形   -5与+5 控制着中间灰色线条的宽度
        RectF lineRect = new RectF(0, mHeight / 2 - 5, mWidth, mHeight / 2 + 5);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setStrokeWidth(1);//设置线条的线宽
        mPaint.setColor(mLineColor);
        canvas.drawRoundRect(lineRect, 20, 20, mPaint);//绘制线条
        //绘制中间的线,选择的范围的线
        mPaint.setColor(mCenterColor);
        RectF doneRect = new RectF(mStartX - mCircleRadius / 2, mHeight / 2 - 10, mEndX + mCircleRadius / 2, mHeight / 2 + 10);
        canvas.drawRoundRect(doneRect, 20, 20, mPaint);
        //按照进度绘制位置
        mPaint.setStyle(Paint.Style.STROKE);//空心圆
        mPaint.setColor(mCenterColor);
        mPaint.setStrokeWidth(5);//设置圆形的线宽
        canvas.drawCircle(mStartX - mCircleRadius, mHeight / 2, mCircleRadius, mPaint);
        canvas.drawCircle(mEndX + mCircleRadius, mHeight / 2, mCircleRadius, mPaint);
        mPaint.setTextSize(25);//设置圆心里文本的大小, SizeUtil.Dp2Px(context, 11)比较好
        if (mListener != null) {
            mListener.selected(mStartValue, mEndValue);
        }
        String start = mStartValue + mIndex;
        String end = mEndValue + mIndex;
        Rect startText = new Rect();
        Rect endText = new Rect();
        mPaint.getTextBounds(start, 0, start.length(), startText);
        mPaint.getTextBounds(end, 0, end.length(), endText);
        mPaint.setStrokeWidth(2);//设置绘制圆心里文本的线宽
        //绘制文字
        mPaint.setColor(getResources().getColor(R.color.colorText));//设置圆形中文本的显示颜色
        canvas.drawText(start, mStartX - mCircleRadius - (startText.right - startText.left) / 2, mHeight / 2 - (startText.bottom + startText.top) / 2, mPaint);
        canvas.drawText(end, mEndX + mCircleRadius - (endText.right + endText.left) / 2, mHeight / 2 - (endText.bottom + endText.top) / 2, mPaint);

    }
}

使用的值 values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 选中的范围的线条的颜色 -->
    <color name="colorPoint">#FF4956</color>
    
    <!-- 圆形上面尺度文本的颜色 -->
    <color name="colorText">#FF4956</color>
    
    <!-- 灰色作为线条的颜色 -->
    <color name="splitGrayColor">#cccccc</color>
    
</resources> 

使用方法:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.timepigtest.RangeBar
        android:id="@+id/main_rengae"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

</RelativeLayout>

代码:

mRangeBar = (RangeBar) findViewById(R.id.main_rengae);
        mRangeBar.setBeginValue(20);//最小值
        mRangeBar.setFinishValue(50);//最大值
        //mRangeBar.setIndex("%");设置圆心里的值带百分号
        mRangeBar.setInitValue(23, 40);//初始化的值
        mRangeBar.setRangeChangeListener(new OnRangeChangedListener() {
            @Override
            public void selected(int start, int end) {
                Log.i("Range:", start + ":" + end);//滑动改变的监听,得到选择的值的范围
            }
        });

效果图:  可以滑动,如果下方需要值显示用线性布局设置权重写几个TextView就O了

 

posted @ 2016-11-26 09:22  ts-android  阅读(218)  评论(0编辑  收藏  举报