android rotate imageview onfling
我正在创建一个旋转旋钮,当我以顺时针或逆时针方向缓慢旋转它时,它可以正常工作。但是如果我想选择一个精确的值,那么它就会变得很难。因为我在每次调用onscroll(ACtion\u Move)时都会增加3的边距。我该怎么办 我想我需要在上一个点和当前点之间有一个精确的角度。但是它会减慢旋转速度。如果用户向右或向左转动轮子,那么我应该在角度上添加什么以使其在各自的方向上平滑旋转 提前感谢您抽出时间android rotate imageview onfling,android,rotation,imageview,touch-event,Android,Rotation,Imageview,Touch Event,我正在创建一个旋转旋钮,当我以顺时针或逆时针方向缓慢旋转它时,它可以正常工作。但是如果我想选择一个精确的值,那么它就会变得很难。因为我在每次调用onscroll(ACtion\u Move)时都会增加3的边距。我该怎么办 我想我需要在上一个点和当前点之间有一个精确的角度。但是它会减慢旋转速度。如果用户向右或向左转动轮子,那么我应该在角度上添加什么以使其在各自的方向上平滑旋转 提前感谢您抽出时间 public class RotaryKnobView extends ImageView { pr
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);
}
}
}
}
公共类RotaryKnobView扩展了ImageView{
专用浮动角度=0f;
私有浮点θ_old=0f;
//图像视图的宽度
私有浮动宽度;
//图像视图的高度
私人浮动高度;
私人最终静态int总重量=26;
私人最终静态双总_角=360;
专用最终静态双余量重量=(总角度/总重量);
专用最终静态双启动重量=5.0d;
私有权重选择器\u活动mContext=null;
私人RotaryKnobListener监听器;
专用静态双倍重量_=0d;
私有静态最终字符串标记=“RotaryKnobView”;
私有位图mBitmap=null;
私有手势检测器mDetector=null;
公共接口RotaryKnobListener{
更改后的公共无效(int arg);
权重选择时的公共无效(双重权重选择);
}
公共无效设置Knoblistener(RotaryKnobListener l){
监听器=l;
}
公共RotaryKnobView(上下文){
超级(上下文);
this.mContext=(WeightPicker_活动)上下文;
初始化();
}
公共RotaryKnobView(上下文、属性集属性){
超级(上下文,attrs);
this.mContext=(WeightPicker_活动)上下文;
初始化();
}
公共RotaryKnobView(上下文上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
this.mContext=(WeightPicker_活动)上下文;
初始化();
}
私有浮点getTheta(浮点x,浮点y){
浮子sx=x-(宽度/2.0f);
浮子sy=y-(高度/2.0f);
浮点长度=(浮点)数学sqrt(sx*sx+sy*sy);
浮动nx=sx/长度;
浮动ny=sy/长度;
浮点θ=(浮点)数学atan2(ny,nx);
最终浮点数rad2deg=(浮点数)(180.0/Math.PI);
浮点θ2=θ*rad2deg;
返回(θ2<0)?θ2+360.0f:θ2;
}
公共void setBitmap(位图mBitmap){
this.mBitmap=mBitmap;
this.setImageBitmap(this.mBitmap);
}
public void getBitmapWidth(){
这个.mBitmap.getWidth();
}
public void getBitmapHeight(){
这个.mBitmap.getHeight();
}
私有布尔值isRotationStarted=false;
公共无效初始化(){
//这个.setImageResource(R.drawable.final\u new\u a);
mDetector=new GestureDetector(mContext,new MygestureRecognitor());
setOnTouchListener(新的OnTouchListener(){
公共布尔onTouch(视图v,运动事件){
//在一次完整旋转后重置角度θ
int action=event.getAction();
int actionCode=action&MotionEvent.action\u掩码;
如果(actionCode==MotionEvent.ACTION\u指针\u向下){
float x=event.getX(0);
float y=event.getY(0);
θ=getTheta(x,y);
Log.i(“theta_old”,theta_old+”);
}else if(actionCode==MotionEvent.ACTION\u MOVE){
使无效();
float x=event.getX(0);
float y=event.getY(0);
浮点θ=getTheta(x,y);
浮动增量θ=θ-θ旧;
θ=θ;
//这里我们确定旋转的方向
int方向=(δθ>0)?1:-1;
如果(方向>0){
//Log.i(“方向>1”,方向+”);
}否则{
//Log.i(“方向<1”,方向+”);
}
角度+=3*方向;
mixcondition();
//Log.i(“当前重量”,
//“重量”
//+((-1)*(角度/余量重量)+起始重量)
// + "");
拾取的重量=((-1)*(角度/余量重量)+起始重量);
对数i(“角度”、“角度”+角度);
通知听者(方向);
notifyListener(拾取的重量);
RotaryKnobView.this.mContext.zoomImageView
.setImageBitmap(cropImage(
RotaryKnobView.this.mContext.mWheelRelativeLayout
.getWidth()/2,0));
}
mDetector.onTouchEvent(事件);
返回true;
}
});
}
私有void mixcondition(){
//停止以在5后旋转。(最小值)
如果(角度>=0){
角度=0;
}
//停止以在30后旋转。(最大值)
//用于逆时针旋转
如果(角度<(-360+余量/重量)){
角度=(浮动)(-360+裕度/重量);
//Toast.makeText(RotaryKnobView.this.mContext,
//“逆时针完成”,Toast.LENGTH_SHORT.show();
}
//用于顺时针旋转
如果(角度>360){
角度=0;
//Toast.makeText(RotaryKnobView.this.mContext,
//“顺时针完成”,
//吐司。长度(短)。show();
}
}
私有void notifyListener(int arg){
if(null!=侦听器)
onKnobChanged(arg);
}
专用void notifyListener(拾取的权重为双倍){
if(null!=侦听器){
listener.onWeightPicked(权重_picked);
}
}
受保护的void onDraw(画布c){
c、 旋转(角度,this.getWidth()/2,this.getHeight()/2);
宽度=this.getWidth();
height=this.getHeight();
//LogInfo.showLogInfo(标记“Width=“+Width”);
//LogInfo.showLogInfo(标记“高度”+高度);
//showLogInfo(“ondrawImageView”、“ondrawImageView”);
这是麦康特