回転ノブを作成していますが、時計回りまたは反時計回りにゆっくりと回転させると正常に動作しますが、正確な値を選択したい場合は難しくなります。 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);
}
}
}
}