package com.wistron.WiCamera;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
public class ArcSeekBar extends View {
private static final String TAG = "ArcSeekBar";
public static final int POS_1ST_QUAD = 0; // 位于第一象限
public static final int POS_2ND_QUAD = 1; // 位于第二象限
public static final int POS_3RT_QUAD = 2; // 位于第三象限
public static final int POS_4ST_QUAD = 3; // 位于第四象限
private boolean mIsTouched = false, mIsFromUser = false,
mIsTouchable = false, mIsEnabled = true;
public static boolean mIsInvalidate = false;
private float mXpos = 0, mYpos = 0, mXDraw = 0, mYDraw = 0;
private double mProgress = 0, mMax = 28, mNewProgress = 0;
private int mWidth = 100, mHeight = 100, mThumbWidth = 77,
mThumbHeight = 77;
private int mQuad = 0; // View所处圆象限
private double mDegree = 0f; // 圆上点与圆点连线的角度:0...pi ~ 0...90
private float mScaleX = 1f; // X轴向压缩比
private float mROffset = 0f; // 圆半径偏移(缩短圆轨迹的半径)
private float mSemiA = 0f, // 长半轴长度: a = width = height
mSemiB = 0f, // 短半轴长度: b = width/2 = height/2
mSemiC = 0f; // 焦点长度 : c = sqrt(a^2 - b^2)
private int mBackgroundResid = 0, mThumbResid = 0, mThumbResidHint = 0,
mSeekBarOffSet = 40, mThumbOffSet = 16;
private Bitmap mBackgroundBmp = null, mThumbBmp = null,
mThumbBmpHint = null;
private Matrix mDrawMatrix = null; // onDraw中使用
private Paint mDrawPaint = null; // onDraw中使用
private int mRadiu = 0;
public OnArcSeekBarChangeListener marcSeekBarChangeListener;
public ArcSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public ArcSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ArcSeekBar(Context context) {
super(context);
init();
}
public void setBackground(int resid) {
Log.w(TAG, "[setBackground]设定背景");
mBackgroundResid = resid;
init();
resize();
}
public void setThumb(int resid) {
mThumbResid = resid;
}
public void setThumbPressed(int resid) {
mThumbResidHint = resid;
}
public void setQuad(int quad) {
Log.w(TAG, "[setQuad]设定象限");
mQuad = quad;
init();
resize();
}
public void setRadiusOffset(float offset) {
mROffset = offset;
init();
resize();
}
@Override
public void setEnabled(boolean enabled) {
// TODO Auto-generated method stub
mIsEnabled = enabled;
super.setEnabled(enabled);
}
public void setMax(int max) {
mMax = max;
}
public void setScaleX(float scaleX) {
Log.w(TAG, "[setScaleX]设定X轴向压缩比");
/*
* steps: 1.压缩Thumb 2.压缩Background 3.压缩轨迹
*/
mScaleX = scaleX;
resize();
}
public void setRadiu(int radiu) {
mRadiu = radiu;
}
@Override
public void setLayoutParams(LayoutParams params) {
Log.w(TAG, "[setLayoutParams]设定LayoutParams");
super.setLayoutParams(params);
if (params != null) {
mWidth = params.width;
mHeight = params.height;
}
if (mWidth < 0) {
mWidth = 200;
}
if (mHeight < 0) {
mHeight = 200;
}
init();
resize();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mIsEnabled) {
return false;
}
boolean state = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int[] location = new int[2];
this.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
Log.i(TAG, "x" + x + "y" + y);
// 圆心点的坐标
// getX()+getWidth()
float centerX = getX() + getWidth();
float centerY = getY() + getHeight();
// 触摸的点和圆心的距离
double length1 = (centerX - event.getRawX())
* (centerX - event.getRawX()) + (centerY - event.getRawY())
* (centerY - event.getRawY());
double length = Math.sqrt(length1);
if (length <= getWidth() - 40 || length > getWidth() + 20) {
mIsTouchable = false;
mIsTouched = false;
state = false;
} else {
mIsTouchable = true;
mIsTouched = true;
state = true;
}
break;
case MotionEvent.ACTION_MOVE:
state = true;
break;
case MotionEvent.ACTION_UP:
mIsTouched = false;
state = true;
break;
case MotionEvent.ACTION_CANCEL:
mIsTouched = false;
state = true;
break;
default:
mIsTouched = false;
break;
}
mXpos = event.getX();
mYpos = event.getY();
if (event.getX() > mWidth) {
mXpos = mWidth;
}
if (event.getY() > mHeight) {
mYpos = mHeight;
}
if (mIsTouchable) {
// Log.e(TAG, "ontouch");
invalidate();
return true;
}
return state;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/*
* 要考虑mQuad 要考虑mScaleX 要考虑mRadiusOffset
*/
// 绘制Background
canvas.drawBitmap(mBackgroundBmp, mDrawMatrix, mDrawPaint);
// 绘制Thumb
switch (mQuad) {
case POS_1ST_QUAD:
mDegree = Math.atan((mHeight - mYpos) / mXpos); // 算出角度
if (Double.isNaN(mDegree)) {
mDegree = 0.01;
}
if (mDegree <= 0) {
mDegree = 0.01;
}
if (mDegree > 0.5 * Math.PI) {
mDegree = 0.5 * Math.PI - 0.01;
}
mSemiA = mHeight - mROffset - mThumbHeight / 2; // 计算长轴
mSemiB = (mWidth - mROffset - mThumbWidth / 2) * mScaleX; // 计算短轴
mXDraw = (float) (mSemiB * Math.cos(mDegree)); // 计算X坐标
mYDraw = -(float) (mSemiA * Math.sin(mDegree)) + mSemiA; // 计算Y坐标
if (mIsTouched) {
canvas.drawBitmap(mThumbBmpHint, mXDraw, mYDraw, mDrawPaint);
Log.w(TAG, "Thumb Pos = " + mXpos + " : " + mYpos);
Log.w(TAG,
"Thumb Pos = "
+ ((float) (mSemiB * Math.cos(mDegree)))
+ " : "
+ (-(float) (mSemiA * Math.sin(mDegree)) + mSemiA));
} else {
canvas.drawBitmap(mThumbBmp, mXDraw, mYDraw, mDrawPaint);
Log.w(TAG, "Thumb Pos = " + mXpos + " : " + mYpos);
Log.w(TAG,
"Thumb Pos = "
+ ((float) (mSemiB * Math.cos(mDegree)))
+ " : "
+ (-(float) (mSemiA * Math.sin(mDegree)) + mSemiA));
}
break;
case POS_2ND_QUAD:
mDegree = Math.atan(mYpos / mXpos); // 算出角度
if (Double.isNaN(mDegree)) {
mDegree = 0.01;
}
if (mDegree <= 0) {
mDegree = 0.01;
}
if (mDegree > 0.5 * Math.PI) {
mDegree = 0.5 * Math.PI - 0.01;
}
mSemiA = mHeight - mROffset - mThumbHeight / 2; // 计算长轴
mSemiB = (mWidth - mROffset - mThumbWidth / 2) * mScaleX; // 计算短轴
mXDraw = (float) (mSemiB * Math.cos(mDegree)); // 计算X坐标
mYDraw = (float) (mSemiA * Math.sin(mDegree)); // 计算Y坐标
if (mIsTouched) {
canvas.drawBitmap(mThumbBmpHint, mXDraw, mYDraw, mDrawPaint);
Log.w(TAG, "Thumb Pos = " + mXpos + " : " + mYpos);
Log.w(TAG,
"Thumb Pos = " + ((float) (mSemiB * Math.cos(mDegree)))
+ " : "
+ ((float) (mSemiA * Math.sin(mDegree))));
} else {
canvas.drawBitmap(mThumbBmp, mXDraw, mYDraw, mDrawPaint);
Log.w(TAG, "Thumb Pos = " + mXpos + " : " + mYpos);
Log.w(TAG,
"Thumb Pos = " + ((float) (mSemiB * Math.cos(mDegree)))
+ " : "
+ ((float) (mSemiA * Math.sin(mDegree))));
}
break;
case POS_3RT_QUAD:
mDegree = Math.atan(mYpos / (mWidth - mXpos)); // 算出角度
if (Double.isNaN(mDegree)) {
mDegree = 0.01;
}
if (mDegree <= 0) {
mDegree = 0.01;
}
if (mDegree > 0.5 * Math.PI) {
mDegree = 0.5 * Math.PI - 0.01;
}
mSemiA = mHeight - mROffset - mThumbHeight / 2; // 计算长轴
mSemiB = (mWidth - mROffset - mThumbWidth / 2) * mScaleX; // 计算短轴
mXDraw = -(float) (mSemiB * Math.cos(mDegree)) + mSemiB; // 计算X坐标
mYDraw = (float) (mSemiA * Math.sin(mDegree)); // 计算Y坐标
if (mIsTouched) {
canvas.drawBitmap(mThumbBmpHint, mXDraw, mYDraw, mDrawPaint);
Log.w(TAG, "Thumb Pos = " + mXpos + " : " + mYpos);
Log.w(TAG,
"Thumb Pos = "
+ (-(float) (mSemiB * Math.cos(mDegree)) + mSemiB)
+ " : "
+ ((float) (mSemiA * Math.sin(mDegree))));
} else {
canvas.drawBitmap(mThumbBmp, mXDraw, mYDraw, mDrawPaint);
Log.w(TAG, "Thumb Pos = " + mXpos + " : " + mYpos);
Log.w(TAG,
"Thumb Pos = "
+ (-(float) (mSemiB * Math.cos(mDegree)) + mSemiB)
+ " : "
+ ((float) (mSemiA * Math.sin(mDegree))));
}
break;
case POS_4ST_QUAD:
if (mIsTouchable) {
if (!mIsFromUser) {
mDegree = Math.atan((mHeight - mYpos) / (mWidth - mXpos)); // 算出角度
if (Double.isNaN(mDegree)) {
mDegree = 0.01;
}
if (mDegree <= 0) {
mDegree = 0.01;
}
if (mDegree > 0.5 * Math.PI) {
mDegree = 0.5 * Math.PI - 0.01;
}
} else {
mDegree = getDegree();
mIsFromUser = false;
}
mSemiA = mHeight - mROffset - mThumbHeight / 2; // 计算长轴
mSemiB = (mWidth - mROffset - mThumbWidth / 2) * mScaleX; // 计算短轴
mXDraw = -(float) (mSemiB * Math.cos(mDegree)) + mSemiB - 20; // 计算X坐标
mYDraw = -(float) (mSemiA * Math.sin(mDegree)) + mSemiA - 15; // 计算Y坐标
double offsetDegree = 0;
mProgress = (mDegree * mMax / (Math.PI / 2 - offsetDegree));
mProgress = mProgress - 5;
if (mProgress <= 0) {
mProgress = 0;
}
if (mProgress >= mMax / 2) {
mProgress = mMax / 2;
}
}
mNewProgress = 2 * mProgress;
if (marcSeekBarChangeListener != null) {
marcSeekBarChangeListener.onProgressChanged(this,
(int) mNewProgress, mIsFromUser);
marcSeekBarChangeListener.onStartTrackingTouch(this);
marcSeekBarChangeListener.onStopTrackingTouch(this);
}
// System.out.println("mprogress------------------" +
// mProgress+"mnewprogress:"+mNewProgress);
if (mYDraw >= 93 || mXDraw < -15) {
mXDraw = -15;
mYDraw = 93;
} else if (mXDraw >= 40 || mYDraw <= 12) {
mXDraw = 40;
mYDraw = 12;
}
if (mIsTouched) {
if (Double.isNaN(mProgress)) {
canvas.drawBitmap(mThumbBmp, -14, mHeight - mThumbHeight
- 5, mDrawPaint);
} else {
canvas.drawBitmap(mThumbBmpHint, mXDraw, mYDraw, mDrawPaint);
}
} else {
if (!mIsTouchable || mProgress == 0 || Double.isNaN(mProgress)) {
canvas.drawBitmap(mThumbBmp, -14, mHeight - mThumbHeight
- 5, mDrawPaint);
} else {
canvas.drawBitmap(mThumbBmp, mXDraw, mYDraw, mDrawPaint);
}
}
break;
}
// 检查Thumb的位置
Log.w("ArcSeekBar", "Draw");
}
protected void init() {
Log.w(TAG, "[init]初始化控件");
Bitmap defBackgroud = null, // 默认背景
defThumb = null, // 默认Thumb
defThumbHint = null; // 默认ThumbHint
Canvas canvas = null;
Paint paint = null;
// 取Background
if (mBackgroundResid == 0) {
defBackgroud = Bitmap.createBitmap(mWidth, mHeight,
Config.ARGB_8888);
canvas = new Canvas(defBackgroud);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setARGB(255, 225, 225, 225);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(5);
canvas.drawARGB(100, 100, 100, 100);
switch (mQuad) {
case POS_1ST_QUAD:
canvas.drawArc(new RectF(mROffset - mWidth + 10, mROffset + 10,
mWidth - mROffset - 10, mHeight - mROffset + mHeight
- 10), ((mQuad + 4 - 1) % 4) * 90, 90, true,
paint);
break;
case POS_2ND_QUAD:
canvas.drawArc(new RectF(mROffset - mWidth + 10, mROffset
- mHeight + 10, mWidth - mROffset - 10, mHeight
- mROffset - 10), ((mQuad + 4 - 1) % 4) * 90, 90, true,
paint);
break;
case POS_3RT_QUAD:
canvas.drawArc(new RectF(mROffset + 10,
mROffset - mHeight + 10, mWidth - mROffset + mWidth
- 10, mHeight - mROffset - 10),
((mQuad + 4 - 1) % 4) * 90, 90, true, paint);
break;
case POS_4ST_QUAD:
canvas.drawArc(new RectF(mROffset + 10, mROffset + 10, mWidth
- mROffset + mWidth - 10, mHeight - mROffset + mHeight
- 10), ((mQuad + 4 - 1) % 4) * 90, 90, true, paint);
break;
}
mBackgroundBmp = defBackgroud;
mROffset = -5;
} else {
mBackgroundBmp = Bitmap.createScaledBitmap(BitmapFactory
.decodeResource(getResources(), mBackgroundResid), mWidth,
mHeight, true);
}
// 取Thumb
if (mThumbResid == 0) {
defThumb = Bitmap.createBitmap(20, 20, Config.ARGB_8888);
canvas = new Canvas(defThumb);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setARGB(255, 255, 205, 205);
paint.setStyle(Style.FILL);
canvas.drawArc(new RectF(0, 0, 20, 20), 0, 360, true, paint);
mThumbBmp = defThumb;
} else {
mThumbBmp = BitmapFactory.decodeResource(getResources(),
mThumbResid);
}
// 取Thumb Hint
if (mThumbResidHint == 0) {
defThumbHint = Bitmap.createBitmap(20, 20, Config.ARGB_8888);
canvas = new Canvas(defThumbHint);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setARGB(255, 205, 255, 205);
paint.setStyle(Style.FILL);
canvas.drawArc(new RectF(0, 0, 20, 20), 0, 360, true, paint);
mThumbBmpHint = defThumbHint;
} else {
mThumbBmpHint = BitmapFactory.decodeResource(getResources(),
mThumbResidHint);
}
// 初始化状态
mWidth = mBackgroundBmp.getWidth();
mHeight = mBackgroundBmp.getHeight();
mProgress = 0;
// if (mMax == 0) {
// mMax = 100;
// }
switch (mQuad) {
case POS_1ST_QUAD:
mXpos = 0.001f;
mYpos = mHeight;
break;
case POS_2ND_QUAD:
mXpos = mWidth;
mYpos = 0.001f;
break;
case POS_3RT_QUAD:
mXpos = 0.001f;
mYpos = 0.001f;
break;
case POS_4ST_QUAD:
mXpos = mWidth;
mYpos = 0.001f;
break;
}
// 初始化onDraw使用的工具
mDrawMatrix = new Matrix();
mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
protected void resize() {
Log.w(TAG, "[resize]重测控件");
mBackgroundBmp = Bitmap.createScaledBitmap(mBackgroundBmp,
(int) (mWidth * mScaleX), (int) mHeight, false);
mThumbBmp = Bitmap.createScaledBitmap(mThumbBmp,
(int) (mThumbWidth * mScaleX), (int) mThumbHeight, false);
mThumbBmpHint = Bitmap.createScaledBitmap(mThumbBmpHint,
(int) (mThumbWidth * mScaleX), (int) mThumbHeight, false);
switch (mQuad) {
case POS_1ST_QUAD:
mXpos = 0.001f;
mYpos = mHeight;
break;
case POS_2ND_QUAD:
mXpos = mWidth * mScaleX;
mYpos = 0.001f;
break;
case POS_3RT_QUAD:
mXpos = 0.001f;
mYpos = 0.001f;
break;
case POS_4ST_QUAD:
mXpos = mWidth * mScaleX;
mYpos = 0.001f;
break;
}
}
/**
* ArcSeekBar事件监听接口
*
* @author WH1107028
*
*/
public interface OnArcSeekBarChangeListener {
public void onStopTrackingTouch(ArcSeekBar seekBar);
public void onStartTrackingTouch(ArcSeekBar seekBar);
public void onProgressChanged(ArcSeekBar seekBar, int progress,
boolean fromUser);
}
public void setOnSeekBarChangeListener(OnArcSeekBarChangeListener listener) {
this.marcSeekBarChangeListener = listener;
}
public OnArcSeekBarChangeListener getOnSeekBarChangeListener() {
return marcSeekBarChangeListener;
}
public void setProgress(int progress) {
mIsFromUser = true;
mProgress = progress;
mDegree = (((double) progress / (double) mMax) * Math.PI / 2);
invalidate();
}
private double getDegree() {
return mDegree;
}
}