我正在创建一个旋转旋钮,当我顺时针或逆时针方向缓慢旋转它时它工作正常。但是如果我想选择一个精确的值,那么它变得很难。因为我在每次调用 onscroll(ACtion_Move) 时添加了 3 的边距. 我应该怎么办 。
我认为我需要在前一点和当前点之间有一个精确的角度。但是它会减慢旋转速度。假设用户将轮子向右或向左转动,那么我应该添加什么角度才能在各自的方向上平滑地旋转它。
提前感谢您的时间。
public class RotaryKnobView extends ImageView {
private float angle = 0f;
private float theta_old = 0f;
// width of imageview
private float width;
// height of imageview
private float height;
private final static int TOTAL_WEIGHT = 26;
private final static double TOTAL_ANGLE = 360;
private final static double MARGIN_BT_WEIGHT = (TOTAL_ANGLE / TOTAL_WEIGHT);
private final static double STARTING_WEIGHT = 5.0d;
private WeightPicker_Activity mContext = null;
private RotaryKnobListener listener;
private static double Weight_Picked = 0d;
private static final String TAG = "RotaryKnobView";
private Bitmap mBitmap = null;
private GestureDetector mDetector = null;
public interface RotaryKnobListener {
public void onKnobChanged(int arg);
public void onWeightPicked(double weightPicked);
}
public void setKnobListener(RotaryKnobListener l) {
listener = l;
}
public RotaryKnobView(Context context) {
super(context);
this.mContext = (WeightPicker_Activity) context;
initialize();
}
public RotaryKnobView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = (WeightPicker_Activity) context;
initialize();
}
public RotaryKnobView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mContext = (WeightPicker_Activity) context;
initialize();
}
private float getTheta(float x, float y) {
float sx = x - (width / 2.0f);
float sy = y - (height / 2.0f);
float length = (float) Math.sqrt(sx * sx + sy * sy);
float nx = sx / length;
float ny = sy / length;
float theta = (float) Math.atan2(ny, nx);
final float rad2deg = (float) (180.0 / Math.PI);
float theta2 = theta * rad2deg;
return (theta2 < 0) ? theta2 + 360.0f : theta2;
}
public void setBitmap(Bitmap mBitmap) {
this.mBitmap = mBitmap;
this.setImageBitmap(this.mBitmap);
}
public void getBitmapWidth() {
this.mBitmap.getWidth();
}
public void getBitmapHeight() {
this.mBitmap.getHeight();
}
private boolean isRotationStarted = false;
public void initialize() {
// this.setImageResource(R.drawable.final_new_a);
mDetector = new GestureDetector(mContext, new MyGestureRecognizer());
setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// reset angle theta after one complete rotation
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
if (actionCode == MotionEvent.ACTION_POINTER_DOWN) {
float x = event.getX(0);
float y = event.getY(0);
theta_old = getTheta(x, y);
Log.i("theta_old", theta_old + "");
} else if (actionCode == MotionEvent.ACTION_MOVE) {
invalidate();
float x = event.getX(0);
float y = event.getY(0);
float theta = getTheta(x, y);
float delta_theta = theta - theta_old;
theta_old = theta;
// here we determine the direction of rotation
int direction = (delta_theta > 0) ? 1 : -1;
if (direction > 0) {
// Log.i("Direction > 1", direction + "");
} else {
// Log.i("Direction < 1", direction + "");
}
angle += 3 * direction;
mixMixCondition();
// Log.i("Current Weight",
// "Weight"
// + (((-1) * (angle / MARGIN_BT_WEIGHT)) + STARTING_WEIGHT)
// + "");
Weight_Picked = (((-1) * (angle / MARGIN_BT_WEIGHT)) + STARTING_WEIGHT);
Log.i("angle", "angle" + angle);
notifyListener(direction);
notifyListener(Weight_Picked);
RotaryKnobView.this.mContext.zoomImageView
.setImageBitmap(cropImage(
RotaryKnobView.this.mContext.mWheelRelativeLayout
.getWidth() / 2, 0));
}
mDetector.onTouchEvent(event);
return true;
}
});
}
private void mixMixCondition() {
// stop to rotate behind 5.(min value)
if (angle >= 0) {
angle = 0;
}
// stop to rotate behind 30.(max value)
// for anticlockwise rotation
if (angle < (-360 + MARGIN_BT_WEIGHT)) {
angle = (float) (-360 + MARGIN_BT_WEIGHT);
// Toast.makeText(RotaryKnobView.this.mContext,
// "Complete anticlockwise", Toast.LENGTH_SHORT).show();
}
// for clockwise rotation
if (angle > 360) {
angle = 0;
// Toast.makeText(RotaryKnobView.this.mContext,
// "Complete Clockwise",
// Toast.LENGTH_SHORT).show();
}
}
private void notifyListener(int arg) {
if (null != listener)
listener.onKnobChanged(arg);
}
private void notifyListener(double weight_picked) {
if (null != listener) {
listener.onWeightPicked(weight_picked);
}
}
protected void onDraw(Canvas c) {
c.rotate(angle, this.getWidth() / 2, this.getHeight() / 2);
width = this.getWidth();
height = this.getHeight();
// LogInfo.showLogInfo(TAG, "Width = " + width);
// LogInfo.showLogInfo(TAG, "Height" + height);
// LogInfo.showLogInfo("ondrawImageView", "ondrawImageView");
this.mContext.zoomImageView.setImageBitmap(cropImage(
mContext.mWheelRelativeLayout.getWidth() / 2, 0));
super.onDraw(c);
}
public Bitmap cropImage(int x, int y) {
Matrix matrix = new Matrix();
this.mContext.mWheelRelativeLayout.buildDrawingCache();
this.mContext.mainBitmap = this.mContext.mWheelRelativeLayout
.getDrawingCache();
Bitmap croppedBitmap = Bitmap.createBitmap(this.mContext.mainBitmap,
x - 50, y + 15, 100, 130, matrix, true);
// Bitmap croppedBitmap2 = Bitmap.createBitmap(croppedBitmap, x-30,
// y+15, 100, 120, matrix,true);
this.mContext.mWheelRelativeLayout.invalidate();
return croppedBitmap;
}
/**
* @return The angle of the unit circle with the image view's center
*/
private double getAngle(double xTouch, double yTouch) {
double x = xTouch - (this.getWidth() / 2d);
double y = this.getHeight() - yTouch - (this.getHeight() / 2d);
switch (getQuadrant(x, y)) {
case 1:
return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
case 2:
case 3:
return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
case 4:
return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
default:
// ignore, does not happen
return 0;
}
}
/**
* @return The selected quadrant.
*/
private static int getQuadrant(double x, double y) {
if (x >= 0) {
return y >= 0 ? 1 : 4;
} else {
return y >= 0 ? 2 : 3;
}
}
private class MyGestureRecognizer extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
LogInfo.showLogInfo("onFling", "VelocityX" + velocityX);
LogInfo.showLogInfo("onFling", "VelocityY" + velocityY);
LogInfo.showLogInfo("onFling", "onFling");
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
}
}