zoukankan      html  css  js  c++  java
  • CircularSeekBar

    /**
     * @author Raghav Sood
     * @version 1
     * @date 26 January, 2013
     */
    package com.appaholics.circularseekbar;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    
    /**
     * The Class CircularSeekBar.
     */
    public class CircularSeekBar extends View {
    
        /** The context */
        private Context mContext;
    
        /** The listener to listen for changes */
        private OnSeekChangeListener mListener;
    
        /** The color of the progress ring */
        private Paint circleColor;
    
        /** the color of the inside circle. Acts as background color */
        private Paint innerColor;
    
        /** The progress circle ring background */
        private Paint circleRing;
    
        /** The angle of progress */
        private int angle = 0;
    
        /** The start angle (12 O'clock */
        private int startAngle = 270;
    
        /** The width of the progress ring */
        private int barWidth = 5;
    
        /** The width of the view */
        private int width;
    
        /** The height of the view */
        private int height;
    
        /** The maximum progress amount */
        private int maxProgress = 100;
    
        /** The current progress */
        private int progress;
    
        /** The progress percent */
        private int progressPercent;
    
        /** The radius of the inner circle */
        private float innerRadius;
    
        /** The radius of the outer circle */
        private float outerRadius;
    
        /** The circle's center X coordinate */
        private float cx;
    
        /** The circle's center Y coordinate */
        private float cy;
    
        /** The left bound for the circle RectF */
        private float left;
    
        /** The right bound for the circle RectF */
        private float right;
    
        /** The top bound for the circle RectF */
        private float top;
    
        /** The bottom bound for the circle RectF */
        private float bottom;
    
        /** The X coordinate for the top left corner of the marking drawable */
        private float dx;
    
        /** The Y coordinate for the top left corner of the marking drawable */
        private float dy;
    
        /** The X coordinate for 12 O'Clock */
        private float startPointX;
    
        /** The Y coordinate for 12 O'Clock */
        private float startPointY;
    
        /**
         * The X coordinate for the current position of the marker, pre adjustment
         * to center
         */
        private float markPointX;
    
        /**
         * The Y coordinate for the current position of the marker, pre adjustment
         * to center
         */
        private float markPointY;
    
        /**
         * The adjustment factor. This adds an adjustment of the specified size to
         * both sides of the progress bar, allowing touch events to be processed
         * more user friendly (yes, I know that's not a word)
         */
        private float adjustmentFactor = 100;
    
        /** The progress mark when the view isn't being progress modified */
        private Bitmap progressMark;
    
        /** The progress mark when the view is being progress modified. */
        private Bitmap progressMarkPressed;
    
        /** The flag to see if view is pressed */
        private boolean IS_PRESSED = false;
    
        /**
         * The flag to see if the setProgress() method was called from our own
         * View's setAngle() method, or externally by a user.
         */
        private boolean CALLED_FROM_ANGLE = false;
    
        private boolean SHOW_SEEKBAR = true;
    
        /** The rectangle containing our circles and arcs. */
        private RectF rect = new RectF();
    
        {
            mListener = new OnSeekChangeListener() {
    
                @Override
                public void onProgressChange(CircularSeekBar view, int newProgress) {
    
                }
            };
    
            circleColor = new Paint();
            innerColor = new Paint();
            circleRing = new Paint();
    
            circleColor.setColor(Color.parseColor("#ff33b5e5")); // Set default
            // progress
            // color to holo
            // blue.
            innerColor.setColor(Color.BLACK); // Set default background color to
            // black
            circleRing.setColor(Color.GRAY);// Set default background color to Gray
    
            circleColor.setAntiAlias(true);
            innerColor.setAntiAlias(true);
            circleRing.setAntiAlias(true);
    
            circleColor.setStrokeWidth(5);
            innerColor.setStrokeWidth(5);
            circleRing.setStrokeWidth(5);
    
            circleColor.setStyle(Paint.Style.FILL);
        }
    
        /**
         * Instantiates a new circular seek bar.
         * 
         * @param context
         *            the context
         * @param attrs
         *            the attrs
         * @param defStyle
         *            the def style
         */
        public CircularSeekBar(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            mContext = context;
            initDrawable();
        }
    
        /**
         * Instantiates a new circular seek bar.
         * 
         * @param context
         *            the context
         * @param attrs
         *            the attrs
         */
        public CircularSeekBar(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            initDrawable();
        }
    
        /**
         * Instantiates a new circular seek bar.
         * 
         * @param context
         *            the context
         */
        public CircularSeekBar(Context context) {
            super(context);
            mContext = context;
            initDrawable();
        }
    
        /**
         * Inits the drawable.
         */
        public void initDrawable() {
            progressMark = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.scrubber_control_normal_holo);
            progressMarkPressed = BitmapFactory.decodeResource(mContext.getResources(),
                    R.drawable.scrubber_control_pressed_holo);
        }
    
        /*
         * (non-Javadoc)
         * 
         * @see android.view.View#onMeasure(int, int)
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            width = getWidth(); // Get View Width
            height = getHeight();// Get View Height
    
            int size = (width > height) ? height : width; // Choose the smaller
            // between width and
            // height to make a
            // square
    
            cx = width / 2; // Center X for circle
            cy = height / 2; // Center Y for circle
            outerRadius = size / 2; // Radius of the outer circle
    
            innerRadius = outerRadius - barWidth; // Radius of the inner circle
    
            left = cx - outerRadius; // Calculate left bound of our rect
            right = cx + outerRadius;// Calculate right bound of our rect
            top = cy - outerRadius;// Calculate top bound of our rect
            bottom = cy + outerRadius;// Calculate bottom bound of our rect
    
            startPointX = cx; // 12 O'clock X coordinate
            startPointY = cy - outerRadius;// 12 O'clock Y coordinate
            markPointX = startPointX;// Initial locatino of the marker X coordinate
            markPointY = startPointY;// Initial locatino of the marker Y coordinate
    
            rect.set(left, top, right, bottom); // assign size to rect
        }
    
        /*
         * (non-Javadoc)
         * 
         * @see android.view.View#onDraw(android.graphics.Canvas)
         */
        @Override
        protected void onDraw(Canvas canvas) {
    
    
            canvas.drawCircle(cx, cy, outerRadius, circleRing);
            canvas.drawArc(rect, startAngle, angle, true, circleColor);
            canvas.drawCircle(cx, cy, innerRadius, innerColor);
            if(SHOW_SEEKBAR){
                dx = getXFromAngle();
                dy = getYFromAngle();
                drawMarkerAtProgress(canvas);
            }
            super.onDraw(canvas);
        }
    
        /**
         * Draw marker at the current progress point onto the given canvas.
         * 
         * @param canvas
         *            the canvas
         */
        public void drawMarkerAtProgress(Canvas canvas) {
            if (IS_PRESSED) {
                canvas.drawBitmap(progressMarkPressed, dx, dy, null);
            } else {
                canvas.drawBitmap(progressMark, dx, dy, null);
            }
        }
    
        /**
         * Gets the X coordinate of the arc's end arm's point of intersection with
         * the circle
         * 
         * @return the X coordinate
         */
        public float getXFromAngle() {
            int size1 = progressMark.getWidth();
            int size2 = progressMarkPressed.getWidth();
            int adjust = (size1 > size2) ? size1 : size2;
            float x = markPointX - (adjust / 2);
            return x;
        }
    
        /**
         * Gets the Y coordinate of the arc's end arm's point of intersection with
         * the circle
         * 
         * @return the Y coordinate
         */
        public float getYFromAngle() {
            int size1 = progressMark.getHeight();
            int size2 = progressMarkPressed.getHeight();
            int adjust = (size1 > size2) ? size1 : size2;
            float y = markPointY - (adjust / 2);
            return y;
        }
    
        /**
         * Get the angle.
         * 
         * @return the angle
         */
        public int getAngle() {
            return angle;
        }
    
        /**
         * Set the angle.
         * 
         * @param angle
         *            the new angle
         */
        public void setAngle(int angle) {
            this.angle = angle;
            float donePercent = (((float) this.angle) / 360) * 100;
            float progress = (donePercent / 100) * getMaxProgress();
            setProgressPercent(Math.round(donePercent));
            CALLED_FROM_ANGLE = true;
            setProgress(Math.round(progress));
        }
    
        /**
         * Sets the seek bar change listener.
         * 
         * @param listener
         *            the new seek bar change listener
         */
        public void setSeekBarChangeListener(OnSeekChangeListener listener) {
            mListener = listener;
        }
    
        /**
         * Gets the seek bar change listener.
         * 
         * @return the seek bar change listener
         */
        public OnSeekChangeListener getSeekBarChangeListener() {
            return mListener;
        }
    
        /**
         * Gets the bar width.
         * 
         * @return the bar width
         */
        public int getBarWidth() {
            return barWidth;
        }
    
        /**
         * Sets the bar width.
         * 
         * @param barWidth
         *            the new bar width
         */
        public void setBarWidth(int barWidth) {
            this.barWidth = barWidth;
        }
    
        /**
         * The listener interface for receiving onSeekChange events. The class that
         * is interested in processing a onSeekChange event implements this
         * interface, and the object created with that class is registered with a
         * component using the component's
         * <code>setSeekBarChangeListener(OnSeekChangeListener)<code> method. When
         * the onSeekChange event occurs, that object's appropriate
         * method is invoked.
         * 
         * @see OnSeekChangeEvent
         */
        public interface OnSeekChangeListener {
    
            /**
             * On progress change.
             * 
             * @param view
             *            the view
             * @param newProgress
             *            the new progress
             */
            public void onProgressChange(CircularSeekBar view, int newProgress);
        }
    
        /**
         * Gets the max progress.
         * 
         * @return the max progress
         */
        public int getMaxProgress() {
            return maxProgress;
        }
    
        /**
         * Sets the max progress.
         * 
         * @param maxProgress
         *            the new max progress
         */
        public void setMaxProgress(int maxProgress) {
            this.maxProgress = maxProgress;
        }
    
        /**
         * Gets the progress.
         * 
         * @return the progress
         */
        public int getProgress() {
            return progress;
        }
    
        /**
         * Sets the progress.
         * 
         * @param progress
         *            the new progress
         */
        public void setProgress(int progress) {
            if (this.progress != progress) {
                this.progress = progress;
                if (!CALLED_FROM_ANGLE) {
                    int newPercent = (this.progress * 100) / this.maxProgress;
                    int newAngle = (newPercent * 360) / 100 ;
                    this.setAngle(newAngle);
                    this.setProgressPercent(newPercent);
                }
                mListener.onProgressChange(this, this.getProgress());
                CALLED_FROM_ANGLE = false;
            }
        }
    
        /**
         * Gets the progress percent.
         * 
         * @return the progress percent
         */
        public int getProgressPercent() {
            return progressPercent;
        }
    
        /**
         * Sets the progress percent.
         * 
         * @param progressPercent
         *            the new progress percent
         */
        public void setProgressPercent(int progressPercent) {
            this.progressPercent = progressPercent;
        }
    
        /**
         * Sets the ring background color.
         * 
         * @param color
         *            the new ring background color
         */
        public void setRingBackgroundColor(int color) {
            circleRing.setColor(color);
        }
    
        /**
         * Sets the back ground color.
         * 
         * @param color
         *            the new back ground color
         */
        public void setBackGroundColor(int color) {
            innerColor.setColor(color);
        }
    
        /**
         * Sets the progress color.
         * 
         * @param color
         *            the new progress color
         */
        public void setProgressColor(int color) {
            circleColor.setColor(color);
        }
    
        /*
         * (non-Javadoc)
         * 
         * @see android.view.View#onTouchEvent(android.view.MotionEvent)
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float x = event.getX();
            float y = event.getY();
            boolean up = false;
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_MOVE:
                moved(x, y, up);
                break;
            case MotionEvent.ACTION_UP:
                up = true;
                moved(x, y, up);
                break;
            }
            return true;
        }
    
        /**
         * Moved.
         * 
         * @param x
         *            the x
         * @param y
         *            the y
         * @param up
         *            the up
         */
        private void moved(float x, float y, boolean up) {
            float distance = (float) Math.sqrt(Math.pow((x - cx), 2) + Math.pow((y - cy), 2));
            if (distance < outerRadius + adjustmentFactor && distance > innerRadius - adjustmentFactor && !up) {
                IS_PRESSED = true;
    
                markPointX = (float) (cx + outerRadius * Math.cos(Math.atan2(x - cx, cy - y) - (Math.PI /2)));
                markPointY = (float) (cy + outerRadius * Math.sin(Math.atan2(x - cx, cy - y) - (Math.PI /2)));
    
                float degrees = (float) ((float) ((Math.toDegrees(Math.atan2(x - cx, cy - y)) + 360.0)) % 360.0);
                // and to make it count 0-360
                if (degrees < 0) {
                    degrees += 2 * Math.PI;
                }
    
                setAngle(Math.round(degrees));
                invalidate();
    
            } else {
                IS_PRESSED = false;
                invalidate();
            }
    
        }
    
        /**
         * Gets the adjustment factor.
         * 
         * @return the adjustment factor
         */
        public float getAdjustmentFactor() {
            return adjustmentFactor;
        }
    
        /**
         * Sets the adjustment factor.
         * 
         * @param adjustmentFactor
         *            the new adjustment factor
         */
        public void setAdjustmentFactor(float adjustmentFactor) {
            this.adjustmentFactor = adjustmentFactor;
        }
    
        /**
         * To display seekbar
         */
        public void ShowSeekBar() {
            SHOW_SEEKBAR = true;
        }
    
        /**
         * To hide seekbar
         */
        public void hideSeekBar() {
            SHOW_SEEKBAR = false;
        }
    }
  • 相关阅读:
    hdu 2896 AC自动机模版题
    快递公司送货员送到货时,打电话通知客户来取的改进
    Scala数据类型中的Symbol(符号文本)
    hdu 3065 AC自动机模版题
    Oracle DB 复制数据库
    Java打包生成exe(使用exe4j和inno setup)
    C#的Lambda表达式嵌套例子
    WPF设置控件获得焦点FocusManager
    Winform给TextBox设置默认值(获取焦点后默认值消失)
    使用signtool.exe来验证程序的数字签名是否成功(命令行)
  • 原文地址:https://www.cnblogs.com/newsouls/p/4937181.html
Copyright © 2011-2022 走看看