CircularSeekBar 自定义 圆形 seekbar
2015-12-25 16:58
429 查看
Android 中的 seekBar会被开发者经常用到,用的最多的空拍是控制音量。但是有时后为了更好的UI效果,横着的拖动条不能满足我们项目的需要,我们可能需要竖直的或者圆形的拖动条,那这两种样式的类SeekBar的效果如何实现呢,接下来小编会一一给出效果和源码。接下来,先说一说圆形的效果吧,有图有真相,请看图:
![](http://img.blog.csdn.net/20130821120858125?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvempicGt1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20130821120932671?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvempicGt1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](http://img.blog.csdn.net/20130821121015312?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvempicGt1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
看过图之后是不是觉得很炫,自己赞一个,下面给出源码:
/values/attr.xml:
[html] view
plaincopyprint?
<?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:
[java] view
plaincopyprint?
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:
[html] view
plaincopyprint?
<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:
[java] view
plaincopyprint?
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 + "");
}
}
小编很辛苦,请尊重菜鸟的劳动成果,转载请注明出处:/article/1386305.html
看过图之后是不是觉得很炫,自己赞一个,下面给出源码:
/values/attr.xml:
[html] view
plaincopyprint?
<?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:
[java] view
plaincopyprint?
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:
[html] view
plaincopyprint?
<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:
[java] view
plaincopyprint?
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 + "");
}
}
小编很辛苦,请尊重菜鸟的劳动成果,转载请注明出处:/article/1386305.html
相关文章推荐
- 在线CRM企业:如何在风投潮中屹立?
- 入门训练 序列求和
- js数据过滤
- JAVA输入
- C++学习:const关键字和常量
- iOS项目重构周记(一)
- 面向对象 抽象类与接口
- c#面向对象基础 重写、虚方法、抽象类
- 曝光!!!扫码生活 App 其实是一个垃圾应用,毫无用处,下面我就给大家说说理由吧!
- UVA 12265 Selling Land
- NSURL的一些属性
- highlight工具
- 关于adb push 带空格的文件到机台中
- Android内存泄露分析(MemoryAnalyzer工具)
- Linux Shell编程入门
- Category类别
- 判断任意两台计算机的IP地址是否属于同一子网络
- 学习文章---qperf测量网络带宽和延迟
- Redis与Memcached的区别
- ICMP