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 {
- }
- }
- @Override
- protected 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);
- }
- @Override
- protected 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;
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- // Convert coordinates to our internal coordinate system
- float 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 pointer
- mAngle = (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 };
- }
- @Override
- protected Parcelable onSaveInstanceState() {
- Parcelable superState = super.onSaveInstanceState();
- Bundle state = new Bundle();
- state.putParcelable(STATE_PARENT, superState);
- state.putFloat(STATE_ANGLE, mAngle);
- return state;
- }
- @Override
- protected 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 implements
- OnCircleSeekBarChangeListener {
- private ZJBCircleSeekBar circleSeekBar;
- TextView textView;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- circleSeekBar = (ZJBCircleSeekBar) findViewById(R.id.c);
- textView = (TextView) findViewById(R.id.text);
- circleSeekBar.setOnSeekBarChangeListener(this);
- }
- @Override
- public void onProgressChanged(ZJBCircleSeekBar seekBar, int progress,
- boolean fromUser) {
- // TODO Auto-generated method stub
- textView.setText(progress + "");
- }
- }
小编很辛苦,请尊重菜鸟的劳动成果,转载请注明出处:http://blog.csdn.net/zjbpku/article/details/10140815