自訂View實現環形SeekBar,view環形seekbar

來源:互聯網
上載者:User

自訂View實現環形SeekBar,view環形seekbar

由於android系統提供的SeekBar是直線型的。但是有些時候我們需要用到其他形狀的SeekBar,那麼就需要自訂View來實現。這裡只是實現了一個環形的,其他形狀的類似。


如下


自訂View的java代碼


package com.lee.circleseekbar.view;import com.lee.circleseekbar.R;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.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** *  * CircleSeekBar *  * @author lee * */public class CircleSeekBar extends View {    private final boolean DEBUG = true;    private final String TAG = "CircleSeekBar";        private Context mContext = null;    private AttributeSet mAttrs = null;        private Drawable mThumbDrawable = null;    private int mThumbHeight = 0;    private int mThumbWidth = 0;    private int[] mThumbNormal = null;    private int[] mThumbPressed = null;        private int mSeekBarMax = 0;    private Paint mSeekBarBackgroundPaint = null;    private Paint mSeekbarProgressPaint = null;    private RectF mArcRectF = null;        private boolean mIsShowProgressText = false;    private Paint mProgressTextPaint = null;    private int mProgressTextSize = 0;        private int mViewHeight = 0;    private int mViewWidth = 0;    private int mSeekBarSize = 0;    private int mSeekBarRadius = 0;    private int mSeekBarCenterX = 0;    private int mSeekBarCenterY = 0;    private float mThumbLeft = 0;    private float mThumbTop = 0;        private float mSeekBarDegree = 0;    private int mCurrentProgress = 0;        public CircleSeekBar(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        mContext = context;        mAttrs = attrs;        initView();    }        public CircleSeekBar(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;        mAttrs = attrs;        initView();    }        public CircleSeekBar(Context context) {        super(context);        mContext = context;        initView();    }        private void initView(){        if(DEBUG) Log.d(TAG, "initView");        TypedArray localTypedArray = mContext.obtainStyledAttributes(mAttrs, R.styleable.CircleSeekBar);                //thumb的屬性是使用android:thumb屬性進行設定的        //返回的Drawable為一個StateListDrawable類型,即可以實現選中效果的drawable list        //mThumbNormal和mThumbPressed則是用於設定不同狀態的效果,當點擊thumb時設定mThumbPressed,否則設定mThumbNormal        mThumbDrawable = localTypedArray.getDrawable(R.styleable.CircleSeekBar_android_thumb);        mThumbWidth = this.mThumbDrawable.getIntrinsicWidth();        mThumbHeight = this.mThumbDrawable.getIntrinsicHeight();                mThumbNormal = new int[]{-android.R.attr.state_focused, -android.R.attr.state_pressed,                 -android.R.attr.state_selected, -android.R.attr.state_checked};        mThumbPressed = new int[]{android.R.attr.state_focused, android.R.attr.state_pressed,                 android.R.attr.state_selected, android.R.attr.state_checked};                float progressWidth = localTypedArray.getDimension(R.styleable.CircleSeekBar_progress_width, 5);        int progressBackgroundColor = localTypedArray.getColor(R.styleable.CircleSeekBar_progress_background, Color.GRAY);        int progressFrontColor = localTypedArray.getColor(R.styleable.CircleSeekBar_progress_front, Color.BLUE);        mSeekBarMax = localTypedArray.getInteger(R.styleable.CircleSeekBar_progress_max, 100);                mSeekbarProgressPaint = new Paint();        mSeekBarBackgroundPaint = new Paint();                mSeekbarProgressPaint.setColor(progressFrontColor);        mSeekBarBackgroundPaint.setColor(progressBackgroundColor);                mSeekbarProgressPaint.setAntiAlias(true);        mSeekBarBackgroundPaint.setAntiAlias(true);                mSeekbarProgressPaint.setStyle(Paint.Style.STROKE);        mSeekBarBackgroundPaint.setStyle(Paint.Style.STROKE);                mSeekbarProgressPaint.setStrokeWidth(progressWidth);        mSeekBarBackgroundPaint.setStrokeWidth(progressWidth);                mArcRectF = new RectF();                mIsShowProgressText = localTypedArray.getBoolean(R.styleable.CircleSeekBar_show_progress_text, false);        int progressTextStroke = (int) localTypedArray.getDimension(R.styleable.CircleSeekBar_progress_text_stroke_width, 5);        int progressTextColor = localTypedArray.getColor(R.styleable.CircleSeekBar_progress_text_color, Color.GREEN);        mProgressTextSize = (int) localTypedArray.getDimension(R.styleable.CircleSeekBar_progress_text_size, 50);        mProgressTextPaint = new Paint();        mProgressTextPaint.setColor(progressTextColor);        mProgressTextPaint.setAntiAlias(true);        mProgressTextPaint.setStrokeWidth(progressTextStroke);        mProgressTextPaint.setTextSize(mProgressTextSize);                localTypedArray.recycle();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        if(DEBUG) Log.d(TAG, "onMeasure");        mViewWidth = getWidth();        mViewHeight = getHeight();                mSeekBarSize = mViewWidth > mViewHeight ? mViewHeight : mViewWidth;        mSeekBarCenterX = mViewWidth / 2;        mSeekBarCenterY = mViewHeight / 2;                mSeekBarRadius = mSeekBarSize / 2 - mThumbWidth / 2;                int left = mSeekBarCenterX - mSeekBarRadius;        int right = mSeekBarCenterX + mSeekBarRadius;        int top = mSeekBarCenterY - mSeekBarRadius;        int bottom = mSeekBarCenterY + mSeekBarRadius;        mArcRectF.set(left, top, right, bottom);                // 起始位置,三點鐘方向        setThumbPosition(Math.toRadians(mSeekBarDegree));    }        @Override    protected void onDraw(Canvas canvas) {        canvas.drawCircle(mSeekBarCenterX, mSeekBarCenterY, mSeekBarRadius,                mSeekBarBackgroundPaint);        canvas.drawArc(this.mArcRectF, 0.0F, mSeekBarDegree, false, mSeekbarProgressPaint);        drawThumbBitmap(canvas);        drawProgressText(canvas);                super.onDraw(canvas);    }        private void drawThumbBitmap(Canvas canvas) {        this.mThumbDrawable.setBounds((int) mThumbLeft, (int) mThumbTop,                (int) (mThumbLeft + mThumbWidth), (int) (mThumbTop + mThumbHeight));        this.mThumbDrawable.draw(canvas);    }        private void drawProgressText(Canvas canvas) {        if (true == mIsShowProgressText){            float textWidth = mProgressTextPaint.measureText("" + mCurrentProgress);            canvas.drawText("" + mCurrentProgress, mSeekBarCenterX - textWidth / 2, mSeekBarCenterY                    + mProgressTextSize / 2, mProgressTextPaint);        }    }        @Override    public boolean onTouchEvent(MotionEvent event) {        float eventX = event.getX();        float eventY = event.getY();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                seekTo(eventX, eventY, false);                break ;                            case MotionEvent.ACTION_MOVE:                seekTo(eventX, eventY, false);                break ;                            case MotionEvent.ACTION_UP:                seekTo(eventX, eventY, true);                break ;        }        return true;    }    private void seekTo(float eventX, float eventY, boolean isUp) {        if (true == isPointOnThumb(eventX, eventY) && false == isUp) {            mThumbDrawable.setState(mThumbPressed);            double radian = Math.atan2(eventY - mSeekBarCenterY, eventX - mSeekBarCenterX);            /*             * 由於atan2返回的值為[-pi,pi]             * 因此需要將弧度值轉換一下,使得區間為[0,2*pi]             */            if (radian < 0){                radian = radian + 2*Math.PI;            }            if(DEBUG) Log.e(TAG, "seekTo radian = " + radian);            setThumbPosition(radian);                        mSeekBarDegree = (float) Math.round(Math.toDegrees(radian));            mCurrentProgress = (int) (mSeekBarMax * mSeekBarDegree / 360);            invalidate();        }else{            mThumbDrawable.setState(mThumbNormal);            invalidate();        }    }    private boolean isPointOnThumb(float eventX, float eventY) {        boolean result = false;        double distance = Math.sqrt(Math.pow(eventX - mSeekBarCenterX, 2)                + Math.pow(eventY - mSeekBarCenterY, 2));        if (distance < mSeekBarSize && distance > (mSeekBarSize / 2 - mThumbWidth)){            result = true;        }        return result;    }        private void setThumbPosition(double radian) {        if(DEBUG) Log.v(TAG, "setThumbPosition radian = " + radian);        double x = mSeekBarCenterX + mSeekBarRadius * Math.cos(radian);        double y = mSeekBarCenterY + mSeekBarRadius * Math.sin(radian);        mThumbLeft = (float) (x - mThumbWidth / 2);        mThumbTop = (float) (y - mThumbHeight / 2);    }        /*     * 增加set方法,用於在java代碼中調用     */    public void setProgress(int progress) {        if(DEBUG) Log.v(TAG, "setProgress progress = " + progress);        if (progress > mSeekBarMax){            progress = mSeekBarMax;        }        if (progress < 0){            progress = 0;        }        mCurrentProgress = progress;        mSeekBarDegree = (progress * 360 / mSeekBarMax);        if(DEBUG) Log.d(TAG, "setProgress mSeekBarDegree = " + mSeekBarDegree);        setThumbPosition(Math.toRadians(mSeekBarDegree));                invalidate();    }        public int getProgress(){        return mCurrentProgress;    }        public void setProgressMax(int max){        if(DEBUG) Log.v(TAG, "setProgressMax max = " + max);        mSeekBarMax = max;    }        public int getProgressMax(){        return mSeekBarMax;    }        public void setProgressThumb(int thumbId){        mThumbDrawable = mContext.getResources().getDrawable(thumbId);    }        public void setProgressWidth(int width){        if(DEBUG) Log.v(TAG, "setProgressWidth width = " + width);        mSeekbarProgressPaint.setStrokeWidth(width);        mSeekBarBackgroundPaint.setStrokeWidth(width);    }        public void setProgressBackgroundColor(int color){        mSeekBarBackgroundPaint.setColor(color);    }        public void setProgressFrontColor(int color){        mSeekbarProgressPaint.setColor(color);    }        public void setProgressTextColor(int color){        mProgressTextPaint.setColor(color);    }        public void setProgressTextSize(int size){        if(DEBUG) Log.v(TAG, "setProgressTextSize size = " + size);        mProgressTextPaint.setTextSize(size);    }        public void setProgressTextStrokeWidth(int width){        if(DEBUG) Log.v(TAG, "setProgressTextStrokeWidth width = " + width);        mProgressTextPaint.setStrokeWidth(width);    }        public void setIsShowProgressText(boolean isShow){        mIsShowProgressText = isShow;    }}


xml檔案如下
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:circle_seekbar="http://schemas.android.com/apk/res/com.lee.circleseekbar"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <com.lee.circleseekbar.view.CircleSeekBar        android:id="@+id/circle_seekbar"        android:layout_width="200dp"        android:layout_height="200dp"        android:layout_centerInParent="true"        android:thumb="@drawable/thumb"        circle_seekbar:progress_background="@android:color/darker_gray"        circle_seekbar:progress_front="@android:color/holo_blue_light"        circle_seekbar:progress_max="1000"        circle_seekbar:progress_text_color="@android:color/holo_green_light"        circle_seekbar:progress_text_size="30dp"        circle_seekbar:progress_text_stroke_width="4dp"        circle_seekbar:progress_width="2dp"        circle_seekbar:show_progress_text="true" /></RelativeLayout>


attrs屬性檔案如下

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="CircleSeekBar">        <attr name="android:thumb" />        <attr name="progress_width" format="dimension" />        <attr name="progress_background" format="color" />        <attr name="progress_front" format="color" />        <attr name="progress_max" format="integer" />        <attr name="show_progress_text" format="boolean" />        <attr name="progress_text_stroke_width" format="dimension" />        <attr name="progress_text_color" format="color" />        <attr name="progress_text_size" format="dimension" />    </declare-styleable></resources>

activity檔案下

package com.lee.circleseekbar;import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import com.lee.circleseekbar.view.CircleSeekBar;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);                setContentView(R.layout.activity_main);                CircleSeekBar circleSeekBar = (CircleSeekBar) findViewById(R.id.circle_seekbar);        circleSeekBar.setProgress(100);        circleSeekBar.setProgressFrontColor(Color.RED);        //circleSeekBar.setProgressWidth(20);        }}




Demo

http://download.csdn.net/detail/ly0904010214/8370879




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.