android CircularSeekBar

来源:互联网 发布:数据分析师累不累 编辑:程序博客网 时间:2024/06/01 07:18

Android 中的 seekBar会被开发者经常用到,用的最多的空拍是控制音量。但是有时后为了更好的UI效果,横着的拖动条不能满足我们项目的需要,我们可能需要竖直的或者圆形的拖动条,那这两种样式的类SeekBar的效果如何实现呢,接下来小编会一一给出效果和源码。接下来,先说一说圆形的效果吧,有图有真相,请看图:

       

看过图之后是不是觉得很炫,自己赞一个,下面给出源码:


/values/attr.xml:  

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="HoloCircleSeekBar">        <attr name="wheel_size" format="integer" />        <attr name="pointer_size" format="integer" />        <attr name="max" format="integer"></attr>        <attr name="show_text" format="boolean"></attr>        <attr name="start_angle" format="integer"></attr>        <attr name="end_angle" format="integer"></attr>        <attr name="text_size" format="integer"></attr>        <attr name="init_position" format="integer"></attr>        <attr name="color" format="string"></attr>        <attr name="wheel_active_color" format="string"></attr>        <attr name="wheel_unactive_color" format="string"></attr>        <attr name="pointer_color" format="string"></attr>        <attr name="pointer_halo_color" format="string"></attr>        <attr name="text_color" format="string"></attr>    </declare-styleable></resources>

ZJBCircleSeekBar.java:

package com.example.circleseekbar;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.SweepGradient;import android.os.Bundle;import android.os.Parcelable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;/** * @author zjbpku * @time 2013-08-21 * @blog http://blog.csdn.net/zjbpku */public class ZJBCircleSeekBar extends View {/** * 保存状态 */private static final String STATE_PARENT = "parent";private static final String STATE_ANGLE = "angle";/*** * 事件监听 */private OnCircleSeekBarChangeListener mOnCircleSeekBarChangeListener;/** * 圆环paint对象 */private Paint mColorWheelPaint;/** * 游标paint对象 */private Paint mPointerHaloPaint;/** * 游标为图画时的paint对象 */private Paint mPointerColor;/** * 圆环的宽度 */private final int mColorWheelStrokeWidth = 10;/** * 游标所在圆环半径 */private final int mPointerRadius = 80;/** * The rectangle enclosing the color wheel. */private RectF mColorWheelRectangle = new RectF();/** * {@code true} 点击游标 {@code false} 停止 *  * @see #onTouchEvent(MotionEvent) */private boolean mUserIsMovingPointer = false;/** *  */private float mTranslationOffset;/** * 圆环半径 Note: (Re)在onMeasure计算{@link #onMeasure(int, int)} */private float mColorWheelRadius;private float mAngle;private String text;private int conversion = 0;private int max = 100;private String color_attr;private SweepGradient s;private Paint mArcColor;private String wheel_color_attr, wheel_unactive_color_attr,pointer_color_attr, pointer_halo_color_attr;private int init_position;private boolean block_end = false;private float lastX;private int last_radians = 0;private boolean block_start = false;private int arc_finish_radians = 270;// 左下角开始private int start_arc = 135;private float[] pointerPosition;private Paint mColorCenterHalo;private RectF mColorCenterHaloRectangle = new RectF();private int end_wheel;private Bitmap pointerBitmap;private boolean show_text = false;public ZJBCircleSeekBar(Context context) {super(context);init(null, 0);}public ZJBCircleSeekBar(Context context, AttributeSet attrs) {super(context, attrs);init(attrs, 0);}public ZJBCircleSeekBar(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(attrs, defStyle);}private void init(AttributeSet attrs, int defStyle) {final TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.HoloCircleSeekBar, defStyle, 0);initAttributes(a);a.recycle();// mAngle = (float) (-Math.PI / 2);mColorWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mColorWheelPaint.setShader(s);mColorWheelPaint.setColor(Color.BLACK);mColorWheelPaint.setStyle(Paint.Style.STROKE);mColorWheelPaint.setStrokeWidth(mColorWheelStrokeWidth);mColorCenterHalo = new Paint(Paint.ANTI_ALIAS_FLAG);mColorCenterHalo.setColor(Color.CYAN);mColorCenterHalo.setAlpha(0xCC);// mColorCenterHalo.setStyle(Paint.Style.STROKE);// mColorCenterHalo.setStrokeWidth(mColorCenterHaloRectangle.width() /// 2);mPointerHaloPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPointerHaloPaint.setColor(Color.GREEN);mPointerHaloPaint.setStrokeWidth(mPointerRadius + 10);// mPointerHaloPaint.setAlpha(150);// 游标图片pointerBitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.pointer);mPointerColor = new Paint(Paint.ANTI_ALIAS_FLAG);mPointerColor.setStrokeWidth(mPointerRadius);// 设置游标指针的颜色mPointerColor.setColor(Color.GREEN);// 设置游标滑过的背景属性mArcColor = new Paint(Paint.ANTI_ALIAS_FLAG);mArcColor.setColor(Color.GREEN);mArcColor.setStyle(Paint.Style.STROKE);mArcColor.setStrokeWidth(mColorWheelStrokeWidth);arc_finish_radians = (int) calculateAngleFromText(init_position) - 90;if (arc_finish_radians > end_wheel)arc_finish_radians = end_wheel;mAngle = calculateAngleFromRadians(arc_finish_radians > end_wheel ? end_wheel: arc_finish_radians);text = String.valueOf(calculateTextFromAngle(arc_finish_radians));invalidate();}private void initAttributes(TypedArray a) {max = a.getInteger(R.styleable.HoloCircleSeekBar_max, 100);color_attr = a.getString(R.styleable.HoloCircleSeekBar_color);wheel_color_attr = a.getString(R.styleable.HoloCircleSeekBar_wheel_active_color);wheel_unactive_color_attr = a.getString(R.styleable.HoloCircleSeekBar_wheel_unactive_color);pointer_color_attr = a.getString(R.styleable.HoloCircleSeekBar_pointer_color);pointer_halo_color_attr = a.getString(R.styleable.HoloCircleSeekBar_pointer_halo_color);a.getString(R.styleable.HoloCircleSeekBar_text_color);a.getInteger(R.styleable.HoloCircleSeekBar_text_size, 95);init_position = a.getInteger(R.styleable.HoloCircleSeekBar_init_position, 0);start_arc = a.getInteger(R.styleable.HoloCircleSeekBar_start_angle, 0);end_wheel = a.getInteger(R.styleable.HoloCircleSeekBar_end_angle, 360);show_text = a.getBoolean(R.styleable.HoloCircleSeekBar_show_text, true);last_radians = end_wheel;if (init_position < start_arc)init_position = calculateTextFromStartAngle(start_arc);// mAngle = (float) calculateAngleFromText(init_position);if (color_attr != null) {try {Color.parseColor(color_attr);} catch (IllegalArgumentException e) {}Color.parseColor(color_attr);} else {}if (wheel_color_attr != null) {try {Color.parseColor(wheel_color_attr);} catch (IllegalArgumentException e) {}} else {}if (wheel_unactive_color_attr != null) {try {Color.parseColor(wheel_unactive_color_attr);} catch (IllegalArgumentException e) {}} else {}if (pointer_color_attr != null) {try {Color.parseColor(pointer_color_attr);} catch (IllegalArgumentException e) {}} else {}if (pointer_halo_color_attr != null) {try {Color.parseColor(pointer_halo_color_attr);} catch (IllegalArgumentException e) {}} else {}}@Overrideprotected void onDraw(Canvas canvas) {canvas.translate(mTranslationOffset, mTranslationOffset);// 滑过的弧canvas.drawArc(mColorWheelRectangle, start_arc + 270, end_wheel- (start_arc), false, mColorWheelPaint);// 背景弧canvas.drawArc(mColorWheelRectangle, start_arc + 270,(arc_finish_radians) > (end_wheel) ? end_wheel - (start_arc): arc_finish_radians - start_arc, false, mArcColor);// 游标为圆形// canvas.drawCircle(pointerPosition[0], pointerPosition[1],// mPointerRadius, mPointerHaloPaint);//// canvas.drawCircle(pointerPosition[0], pointerPosition[1],// (float) (mPointerRadius / 1.2), mPointerColor);// 游标为方形// canvas.drawRect(pointerPosition[0] - 50, pointerPosition[1] - 30,// pointerPosition[0] + 50, pointerPosition[1] + 30, mPointerColor);// 游标为图片canvas.drawBitmap(pointerBitmap, pointerPosition[0] - 50,pointerPosition[1] - 115, null);// 添加游标上的文字Paint pai = new Paint();pai.setColor(Color.BLACK);pai.setTextSize(50);canvas.drawText(text, pointerPosition[0] - 30, pointerPosition[1] - 40,pai);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int height = getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);int min = Math.min(width, height);setMeasuredDimension(min, min);mTranslationOffset = min * 0.5f;mColorWheelRadius = mTranslationOffset - mPointerRadius;mColorWheelRectangle.set(-mColorWheelRadius, -mColorWheelRadius,mColorWheelRadius, mColorWheelRadius);mColorCenterHaloRectangle.set(-mColorWheelRadius / 2,-mColorWheelRadius / 2, mColorWheelRadius / 2,mColorWheelRadius / 2);pointerPosition = calculatePointerPosition(mAngle);}private int calculateTextFromAngle(float angle) {float m = angle - start_arc;float f = (float) ((end_wheel - start_arc) / m);return (int) (max / f);}private int calculateTextFromStartAngle(float angle) {float m = angle;float f = (float) ((end_wheel - start_arc) / m);return (int) (max / f);}private double calculateAngleFromText(int position) {if (position == 0 || position >= max)return (float) 90;double f = (double) max / (double) position;double f_r = 360 / f;double ang = f_r + 90;return ang;}private int calculateRadiansFromAngle(float angle) {float unit = (float) (angle / (2 * Math.PI));if (unit < 0) {unit += 1;}int radians = (int) ((unit * 360) - ((360 / 4) * 3));if (radians < 0)radians += 360;return radians;}private float calculateAngleFromRadians(int radians) {return (float) (((radians + 270) * (2 * Math.PI)) / 360);}public int getValue() {return conversion;}@Overridepublic boolean onTouchEvent(MotionEvent event) {// Convert coordinates to our internal coordinate systemfloat x = event.getX() - mTranslationOffset;float y = event.getY() - mTranslationOffset;switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// Check whether the user pressed on (or near) the pointermAngle = (float) java.lang.Math.atan2(y, x);block_end = false;block_start = false;mUserIsMovingPointer = true;arc_finish_radians = calculateRadiansFromAngle(mAngle);if (arc_finish_radians > end_wheel) {arc_finish_radians = end_wheel;block_end = true;}if (!block_end && !block_start) {text = String.valueOf(calculateTextFromAngle(arc_finish_radians));pointerPosition = calculatePointerPosition(mAngle);invalidate();}break;case MotionEvent.ACTION_MOVE:if (mUserIsMovingPointer) {mAngle = (float) java.lang.Math.atan2(y, x);int radians = calculateRadiansFromAngle(mAngle);if (last_radians > radians && radians < (360 / 6) && x > lastX&& last_radians > (360 / 6)) {if (!block_end && !block_start)block_end = true;} else if (last_radians >= start_arc&& last_radians <= (360 / 4) && radians <= (360 - 1)&& radians >= ((360 / 4) * 3) && x < lastX) {if (!block_start && !block_end)block_start = true;} else if (radians >= end_wheel && !block_start&& last_radians < radians) {block_end = true;} else if (radians < end_wheel && block_end&& last_radians > end_wheel) {block_end = false;} else if (radians < start_arc && last_radians > radians&& !block_end) {block_start = true;} else if (block_start && last_radians < radians&& radians > start_arc && radians < end_wheel) {block_start = false;}if (block_end) {arc_finish_radians = end_wheel - 1;text = String.valueOf(0);mAngle = calculateAngleFromRadians(arc_finish_radians);pointerPosition = calculatePointerPosition(mAngle);} else if (block_start) {arc_finish_radians = start_arc;mAngle = calculateAngleFromRadians(arc_finish_radians);text = String.valueOf(0);pointerPosition = calculatePointerPosition(mAngle);} else {// text = String.valueOf(calculateTextFromAngle(mAngle));arc_finish_radians = calculateRadiansFromAngle(mAngle);text = String.valueOf(calculateTextFromAngle(arc_finish_radians));pointerPosition = calculatePointerPosition(mAngle);}invalidate();if (mOnCircleSeekBarChangeListener != null)mOnCircleSeekBarChangeListener.onProgressChanged(this,Integer.parseInt(text), true);last_radians = radians;}break;case MotionEvent.ACTION_UP:mUserIsMovingPointer = false;break;}if (event.getAction() == MotionEvent.ACTION_MOVE && getParent() != null) {getParent().requestDisallowInterceptTouchEvent(true);}lastX = x;return true;}/** * Calculate the pointer's coordinates on the color wheel using the supplied * angle. *  * @param angle *            The position of the pointer expressed as angle (in rad). *  * @return The coordinates of the pointer's center in our internal *         coordinate system. */private float[] calculatePointerPosition(float angle) {// if (calculateRadiansFromAngle(angle) > end_wheel)// angle = calculateAngleFromRadians(end_wheel);float x = (float) (mColorWheelRadius * Math.cos(angle));float y = (float) (mColorWheelRadius * Math.sin(angle));return new float[] { x, y };}@Overrideprotected Parcelable onSaveInstanceState() {Parcelable superState = super.onSaveInstanceState();Bundle state = new Bundle();state.putParcelable(STATE_PARENT, superState);state.putFloat(STATE_ANGLE, mAngle);return state;}@Overrideprotected void onRestoreInstanceState(Parcelable state) {Bundle savedState = (Bundle) state;Parcelable superState = savedState.getParcelable(STATE_PARENT);super.onRestoreInstanceState(superState);mAngle = savedState.getFloat(STATE_ANGLE);arc_finish_radians = calculateRadiansFromAngle(mAngle);text = String.valueOf(calculateTextFromAngle(arc_finish_radians));pointerPosition = calculatePointerPosition(mAngle);}public void setOnSeekBarChangeListener(OnCircleSeekBarChangeListener l) {mOnCircleSeekBarChangeListener = l;}public interface OnCircleSeekBarChangeListener {public abstract void onProgressChanged(ZJBCircleSeekBar seekBar,int progress, boolean fromUser);}}

/layout/activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:layout_gravity="center_horizontal"    tools:context=".MainActivity" >    <TextView        android:id="@+id/text"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_centerHorizontal="true"        android:layout_marginTop="80dp"        android:gravity="center_horizontal"        android:textSize="60sp"         android:textColor="#ffff0000"        />    <com.example.circleseekbar.HoloCircleSeekBar        android:id="@+id/c"        android:layout_width="500px"        android:layout_height="500px"        android:layout_centerInParent="true" /></RelativeLayout>

MainActivity.java:

package com.example.circleseekbar;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;import com.example.circleseekbar.ZJBCircleSeekBar.OnCircleSeekBarChangeListener;/** * @author zjbpku * @time 2013-08-21 * @blog http://blog.csdn.net/zjbpku */public class MainActivity extends Activity implementsOnCircleSeekBarChangeListener {private ZJBCircleSeekBar circleSeekBar;TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_main);circleSeekBar = (ZJBCircleSeekBar) findViewById(R.id.c);textView = (TextView) findViewById(R.id.text);circleSeekBar.setOnSeekBarChangeListener(this);}@Overridepublic void onProgressChanged(ZJBCircleSeekBar seekBar, int progress,boolean fromUser) {// TODO Auto-generated method stubtextView.setText(progress + "");}}
小编很辛苦,请尊重菜鸟的劳动成果,转载请注明出处:http://blog.csdn.net/zjbpku/article/details/10140815

原创粉丝点击