Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android實現圖片隨手指旋轉功能

Android實現圖片隨手指旋轉功能

編輯:關於Android編程

在View中進行重繪,主要是通過計算角度及距離來實現。實現類代碼如下:


[java]
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); 
    } 

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中調用代碼:


[java]
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();  
    } 
 
 

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度切換一個模式,點擊每個部分均有響應事件回調到主界面。涉及保密,圖片不給在此給出。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved