Android实现图片随手指旋转功能

在View中进行重绘,主要是通过计算角度及距离来实现。实现类代码如下:

package com.example.roatedemo;

import java.util.Calendar;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class RotateView extends View {
	private Paint mPaint = new Paint();
	private Bitmap bitmaplittele;//中间不动的图片
	private Bitmap bitmapBig;//随手指转动的图片
	private Bitmap bitmapOut;//外围不动的图片
	// 圆心坐标
	private float mPointX = 0, mPointY = 0;

	private int flag = 0;
	// 半径
	private int mRadius = 0;
	// 旋转角度
	private int mAngle = 0;
	private int beginAngle = 0, currentAngle = 0;
	private String TAG = "NewView";
	int bitMap[] = { R.drawable.circle0, R.drawable.circle1, R.drawable.circle2 };
	int imageIndex = 0;
	boolean isUp = false,isTouch=false;
	Context mContext;
	RotateViewListener listener;
	long beginTime,endTime;
	Calendar now;

	public RotateView(Context context, int px, int py, int radius,RotateViewListener listener) {
		super(context);
		mContext = context;
		this.listener = listener;
		mPointX = px;
		mPointY = py;
		mRadius = radius;
		bitmaplittele = BitmapFactory.decodeResource(getResources(),
				R.drawable.a1_pointer).copy(Bitmap.Config.ARGB_8888, true);
		bitmapBig = BitmapFactory.decodeResource(getResources(), bitMap[0])
				.copy(Bitmap.Config.ARGB_8888, true);
		bitmapOut = BitmapFactory.decodeResource(getResources(),
				R.drawable.bigcir).copy(Bitmap.Config.ARGB_8888, true);
		setBackgroundResource(R.drawable.back);
		Log.e(TAG, "RotateViewBegin");		
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent e) {
		switch (e.getAction() & MotionEvent.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			now = Calendar.getInstance();
			beginTime = now.getTimeInMillis();
			beginAngle = computeCurrentAngle(e.getX(), e.getY());
			isUp = false;
			//如果点击触摸范围在圈外,则不处理
			if (getDistance(e.getX(), e.getY())>bitmapOut.getWidth()/2) {
				isTouch=false;
			}else {
				isTouch=true;
			}
			return true;
		case MotionEvent.ACTION_MOVE:
			if (!isTouch) {
				return true;
			}
			currentAngle = computeCurrentAngle(e.getX(), e.getY());
			invalidate();
			return true;
		case MotionEvent.ACTION_UP:
			isUp = true;
			if (!isTouch) {
				return true;
			}
			now = Calendar.getInstance();
			endTime = now.getTimeInMillis();
			if (SetClick(e.getX(), e.getY())) {
				return true;
			}			
			if (mAngle > 0) {
				int count = mAngle / 120 + (mAngle % 120 > 60 ? 1 : 0);
				imageIndex = (imageIndex + count) % 3;
			} else if (mAngle < 0) {
				mAngle = -mAngle;
				int count = mAngle / 120 + (mAngle % 120 > 60 ? 1 : 0);
				imageIndex = (imageIndex + 3 - count) % 3;
			}
			bitmapBig = BitmapFactory.decodeResource(getResources(),
					bitMap[imageIndex]).copy(Bitmap.Config.ARGB_8888, true);
			bitmapBig = adjustPhotoRotation(bitmapBig, imageIndex * 120);
			invalidate();
			if (mAngle >= 60) {
				listener.onModChange(imageIndex);
			}			
			return true;
		}

		return false;
	}

	@Override
	public void onDraw(Canvas canvas) {
		// Log.i(TAG, "onDraw");
		// 大圆
		drawInCenter(canvas, bitmapOut, mPointX, mPointY, TAG);
		// 外圈
		if (isUp) {
			mAngle = 0;
		} else {
			mAngle = currentAngle - beginAngle;
		}

		Bitmap tempBig = adjustPhotoRotation(bitmapBig, mAngle);
		// Log.i(TAG, "mAngle:"+mAngle);
		drawInCenter(canvas, tempBig, mPointX, mPointY + 10, TAG);
		// 小圆(中间的圆心)
		drawInCenter(canvas, bitmaplittele, mPointX, mPointY - 10, TAG);
	}

	Bitmap adjustPhotoRotation(Bitmap bm, final int orientationDegree) {
		if (orientationDegree == 0) {
			return bm;
		}
		Matrix m = new Matrix();
		m.setRotate(orientationDegree, (float) bm.getWidth() / 2,
				(float) bm.getHeight() / 2);

		try {
			Bitmap bm1 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(),
					bm.getHeight(), m, true);

			return bm1;

		} catch (OutOfMemoryError ex) {
		}

		return null;

	}

	private void drawInCenter(Canvas canvas, Bitmap bitmap, float left,
			float top, String text) {
		canvas.drawBitmap(bitmap, left - bitmap.getWidth() / 2,
				top - bitmap.getHeight() / 2, null);
	}

	// 子控件位置改变重新计算角度
	private int computeCurrentAngle(float x, float y) {
		// 根据圆心坐标计算角度
		float distance = (float) Math
				.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY)
						* (y - mPointY)));
		int degree = (int) (Math.acos((x - mPointX) / distance) * 180 / Math.PI);
		if (y < mPointY) {
			degree = -degree;
		}
		if (degree < 0) {
			degree += 360;
		}

		// Log.i("RoundSpinView", "x:" + x + ",y:" + y + ",degree:" + degree);
		return degree;
	}

	// 获取距离圆心的距离
	private float getDistance(float x, float y) {
		// 根据圆心坐标计算角度
		float distance = (float) Math
				.sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY)
						* (y - mPointY)));
		return distance;
	}

	//点击
	private boolean SetClick(float x, float y) {
		float distance = getDistance(x, y);
		if (mAngle>10||mAngle<-10) {
			return false;
		}else if(endTime-beginTime>1000){
			return false;
		}
		if (distance < bitmapBig.getWidth() / 2) {
			int mod = 0;
			
			if (beginAngle < 90 || 330 < beginAngle) {
				mod = (imageIndex+3-1)%3;							
			}
			else if (90 < beginAngle && 210 > beginAngle) {
				mod = (imageIndex+3-2)%3;				
			}
			else{
				mod = imageIndex;				
			}
			//回调到主界面进行处理。
			listener.onModClick(mod);
		}
		return true;
	}
	
	public interface RotateViewListener {		
		void onModClick(int mode);
		void onModChange(int mode);
	}
}

Activity中调用代码:

package com.example.roatedemo;

import com.example.roatedemo.RotateView.RotateViewListener;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends Activity implements RotateViewListener{

	RotateView rotateView;
	String TAG="MainActivity";
	Context mContext;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mContext = this;
		int height,width;
		DisplayMetrics displayMetrics = new DisplayMetrics(); 
		getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
		height = displayMetrics.heightPixels;
		width = displayMetrics.widthPixels;
		Log.i(TAG, "height:"+height);
		Log.i(TAG, "width:"+width);
		rotateView = new RotateView(getApplicationContext(), width/2, height/3, 150,this);

		setContentView(rotateView);
	}
	@Override
	public void onModClick(int mode) {
		String[] clickStrings = new String[] { "1被点击", "2被点击","3被点击" };
		Toast.makeText(mContext, clickStrings[mode], 0).show();
		
	}
	@Override
	public void onModChange(int mode) {
		String[] clickStrings = new String[] { "切换到1", "切换到2","切换到3" };
		Toast.makeText(mContext, clickStrings[mode], 0).show();	
	}


}

布局文件默认即可。

除了实现图片旋转,还实现将图片切成3部分,每部分120度,每转动120度切换一个模式,点击每个部分均有响应事件回调到主界面。涉及保密,图片不给在此给出。

你可能感兴趣的:(Android实现图片随手指旋转功能)