package com.linjun.acuscontroller.userviews;
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.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import java.io.InputStream;
import java.util.HashMap;
/**
* Created by Vander on 2018/7/16.
*/
public class WheelView extends View implements View.OnTouchListener{
Context mContext;
float scale;
private boolean isInit;
private final double PI4 = Math.PI / 4;
public WheelView(Context context) {
super(context);
isInit = true;
mContext = context;
scale = context.getResources().getDisplayMetrics().density ;
this.setBackgroundColor(Color.TRANSPARENT);
initWheelView();
}
public WheelView(Context context, AttributeSet attrs) {
super(context, attrs);
isInit = true;
mContext = context;
scale = context.getResources().getDisplayMetrics().density ;
this.setBackgroundColor(Color.TRANSPARENT);
big_bg = attrs.getAttributeResourceValue(null, "big_circle_src",0);
small_bg = attrs.getAttributeResourceValue(null, "small_circle_src", 0);
initWheelView();
}
public WheelView(Context context, AttributeSet attrs, int paramInt) {
super(context, attrs, paramInt);
isInit = true;
mContext = context;
scale = context.getResources().getDisplayMetrics().density ;
this.setBackgroundColor(Color.TRANSPARENT);
big_bg = attrs.getAttributeResourceValue(null, "big_circle_src",0);
small_bg = attrs.getAttributeResourceValue(null, "small_circle_src", 0);
initWheelView();
}
private int wheel_gravity;
public void setWheelGravity(int gravity){
wheel_gravity = gravity;
}
public void getWheelGravity(){
switch (wheel_gravity){
case Gravity.LEFT:
iniCenter(bigcircle_radius,getHeight() / 2 - bigcircle_radius);
break;
case Gravity.RIGHT:
iniCenter(getWidth() - bigcircle_radius,getHeight() / 2 - bigcircle_radius);
break;
case Gravity.TOP:
iniCenter(getWidth() / 2 - bigcircle_radius,bigcircle_radius);
break;
case Gravity.BOTTOM:
iniCenter(getWidth() / 2 - bigcircle_radius,getHeight() - bigcircle_radius);
break;
case Gravity.LEFT|Gravity.TOP:
iniCenter(bigcircle_radius, bigcircle_radius);
break;
case Gravity.RIGHT|Gravity.TOP:
iniCenter(bigcircle_radius, getWidth() - bigcircle_radius);
break;
case Gravity.LEFT|Gravity.BOTTOM:
iniCenter(bigcircle_radius, getHeight() - bigcircle_radius);
break;
case Gravity.RIGHT|Gravity.BOTTOM:
iniCenter(getWidth() - bigcircle_radius, getHeight() - bigcircle_radius);
break;
default:
iniCenter(bigcircle_radius, getHeight() - bigcircle_radius);
break;
}
}
//设置中心初始值
private float initCenterX, initCenterY;
public void iniCenter(float x, float y){
initCenterX = x;
initCenterY = y;
setCenter(initCenterX, initCenterY);
invalidate();
}
private float centerX, centerY;
public void setCenter(float x, float y){
centerX = x;
centerY = y;
moveCenterX = x;
moveCenterY = y;
invalidate();
}
//小圆中心
private float moveCenterX, moveCenterY;
//大圆
private int big_bg;
private Bitmap bigCircle;
private Paint bigCirclePaint;
private int bigcircle_radius;;
//小圆
private int small_bg;
private Bitmap smallCircle;
private Paint smallCirclePaint;
private int smallcircle_radius;
private void initWheelView(){
bigCirclePaint = new Paint(1);
smallCirclePaint = new Paint(1);
bigcircle_radius = dip2px(60);
smallcircle_radius = bigcircle_radius / 2;
InputStream is = getResources().openRawResource(big_bg);
Bitmap tempMap = BitmapFactory.decodeStream(is);
bigCircle = Bitmap.createScaledBitmap(tempMap, bigcircle_radius * 2, bigcircle_radius * 2, true);
is = getResources().openRawResource(small_bg);
tempMap = BitmapFactory.decodeStream(is);
smallCircle = Bitmap.createScaledBitmap(tempMap, smallcircle_radius * 2, smallcircle_radius * 2, true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//取宽高中的小值,作为宽高值
int w = measure(widthMeasureSpec);
int h = measure(heightMeasureSpec);
//将宽高值传给父容器,告诉父容器我需要占用多少宽高
setMeasuredDimension(w, h);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/** 测量宽高的方法 */
private int measure(int paramInt) {
int i = MeasureSpec.getMode(paramInt);
int j = MeasureSpec.getSize(paramInt);
if (i == 0)//当模式=0时,表示 android:layout_width="wrap_content"
return dip2px(200);//此时设置默认宽高为200
return j;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(isInit){
getWheelGravity();
isInit = false;
}
canvas.drawBitmap(bigCircle, centerX - bigcircle_radius,centerY - bigcircle_radius, bigCirclePaint);
canvas.drawBitmap(smallCircle, moveCenterX - smallcircle_radius, moveCenterY - smallcircle_radius, smallCirclePaint);
}
public int dip2px(float dipValue)
{
return (int)(dipValue * scale + 0.5f) ;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
private float position_X,position_Y;
public float lastAngle,lastDistance;
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
setCenter(event.getX(), event.getY());
if(centerX < bigcircle_radius){
centerX = bigcircle_radius;
} else if (centerX > (getWidth() - bigcircle_radius)){
centerX = getWidth() - bigcircle_radius;
}
if(centerY < bigcircle_radius){
centerY = bigcircle_radius;
} else if (centerY > (getHeight() - bigcircle_radius)){
centerY = getWidth() - bigcircle_radius;
}
this.position_X = (int) event.getX();
this.position_Y = (int) event.getY();
if(wheelViewMoveListener != null){
if ((this.thread != null) && (this.thread.isAlive()))
this.thread.interrupt();
this.thread = new Thread(runnable);
this.thread.start();//手指按下开始
this.lastAngle = getAngle();
if (this.wheelViewMoveListener != null)
//自定义接口处理触摸事件
this.wheelViewMoveListener.onValueChanged(this.lastAngle, getDistance());
}
} else if(event.getAction() == MotionEvent.ACTION_MOVE){
this.position_X = (int) event.getX();
this.position_Y = (int) event.getY();
double d = Math.sqrt(//X坐标的平方+Y坐标的平方再开平方
Math.pow(this.position_X - this.centerX, 2) +
Math.pow(this.position_Y - this.centerY, 2));
if (d > this.bigcircle_radius) {
this.position_X = (int) ((this.position_X - this.centerX)
* this.bigcircle_radius / d + this.centerX);
this.position_Y = (int) ((this.position_Y - this.centerY)
* this.bigcircle_radius / d + this.centerY);
}
moveCenterX = this.position_X;
moveCenterY = this.position_Y;
this.lastAngle = getAngle();
this.lastDistance = getDistance();
invalidate();
//this.lastAngle = (this.lastAngle % 45) > 25 ? ((int)(this.lastAngle / 45) + 1) * 45: (int)(this.lastAngle / 45) * 45;
// if((this.lastAngle % 45) > 22.5){
// moveCenterX = (float) (Math.cos(((int)(this.lastAngle / 45) + 1) * PI4) * this.lastDistance + centerX);
// moveCenterY = (float) (Math.sin(((int)(this.lastAngle / 45) + 1) * PI4) * this.lastDistance + centerY);
//
// } else {
// moveCenterX = (float) (Math.cos(((int)(this.lastAngle / 45)) * PI4) * this.lastDistance + centerX);
// moveCenterY = (float) (Math.sin(((int)(this.lastAngle / 45)) * PI4) * this.lastDistance + centerY);
//
// }
if (this.wheelViewMoveListener != null)
this.wheelViewMoveListener.onValueChanged(this.lastAngle, getDistance());
} else if(event.getAction() == MotionEvent.ACTION_UP){
setCenter(initCenterX,initCenterY);
this.position_X = (int) this.centerX;
this.position_Y = (int) this.centerY;
//if ((this.thread != null) && (this.thread.isAlive()))
this.thread.interrupt();//手指抬起时中断,并做一次位置和方向的监听
this.lastAngle = getAngle();
if (this.wheelViewMoveListener != null)
this.wheelViewMoveListener.onValueChanged(this.lastAngle, getDistance());
}
invalidate();
return true;
}
private float getAngle() {
if (this.position_X > this.centerX) {
if (this.position_Y < this.centerY) {//右上角,第一象限
float m = (float) (90.0D + 57.295779500000002D * Math
.atan((position_Y - this.centerY)
/ (this.position_X - this.centerX)));
this.lastAngle = m;
return m;
}
if (this.position_Y > this.centerY) {//右下角,第二象限
float k = 90 + (float) (57.295779500000002D * Math
.atan((this.position_Y - this.centerY)
/ (this.position_X - this.centerX)));
this.lastAngle = k;
return k;
}
this.lastAngle = 90;
return 90;
}
if (this.position_X < this.centerX) {
if (this.position_Y < this.centerY) {//左上角,第三象限
float j = (float) (57.295779500000002D * Math
.atan((this.position_Y - this.centerY)
/ (this.position_X - this.centerX)) - 90.0D);
j = (j + 360) % 360;
this.lastAngle = j;
return j;
}
if (this.position_Y > this.centerY) {//左下角,第四象限
float i = -90 + (float) (57.295779500000002D * Math
.atan((this.position_Y - this.centerY)
/ (this.position_X - this.centerX)));
i = (i + 360) % 360;
this.lastAngle = i;
return i;
}
this.lastAngle = 270;
return 270;
}
if (this.position_Y == this.centerY) {
this.lastAngle = 0;
return 0;
}
if (this.lastAngle < 0) {
this.lastAngle = 0;
return 0;
}
this.lastAngle = 180;
return 180;
}
/** 得到所处位置与中心的距离(百分比) */
private float getDistance() {
this.lastDistance= (float)(100.0D * Math.sqrt(
Math.pow(this.position_X - this.centerX, 2) +
Math.pow(this.position_Y - this.centerY, 2)
) / this.bigcircle_radius);
return lastDistance;
}
/** 监听时间间隔,默认为100毫秒 */
private long loopInterval = 100L;
/** 手指按下之后的循环监听线程 */
private Thread thread;
/** 事件监听线程的实现 */
private Runnable runnable = new Runnable() {
@Override
public void run() {
while (true) {
if (Thread.interrupted())
return;
post(new Runnable() {
public void run() {
if (WheelView.this.wheelViewMoveListener != null)
WheelView.this.wheelViewMoveListener.onValueChanged(
WheelView.this.lastAngle,
WheelView.this.getDistance());
}
});
try {
Thread.sleep(WheelView.this.loopInterval);
} catch (InterruptedException localInterruptedException) {
}
}
}
};
OnWheelViewMoveListener wheelViewMoveListener;
public void setOnWheelViewMoveListener(OnWheelViewMoveListener listener){
wheelViewMoveListener = listener;
}
public void setOnWheelViewMoveListener(OnWheelViewMoveListener listener, long paramLong) {
this.wheelViewMoveListener = listener;
loopInterval = paramLong;
}
public abstract interface OnWheelViewMoveListener {
/**
* 接口回调函数
* @param angle 角度
* @param distance 距离
*/
public abstract void onValueChanged(float angle, float distance);
}
}