【Android】自定义环形菜单View
生活随笔
收集整理的這篇文章主要介紹了
【Android】自定义环形菜单View
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實現的效果圖:六個小圖片可以跟隨手指滑動繞中心點旋轉
代碼:
package com.example.test_canvas;import java.util.ArrayList; import java.util.List;import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView;public class MyView extends SurfaceView {private final String TAG = "MyView";private final int WHAT_MOVE = 0X013;private final int WHAT_CLICK = 0X014;private final int TIME_CLICK_INTERVAL = 200;// 按下抬起的間隔時間// private Handler mThreadHandler = null;MyDrawableThread mThread = null;private MyViewClickListener mListener = null;private int Radius = 0;// 半徑Bitmap[] mItems = null;private int viewWidth = 0;private int viewHeight = 0;private int centerX = 0;private int centerY = 0;private List<Point> mPoints = new ArrayList<Point>();private Handler mMainHandler = null;public MyView(Context context, AttributeSet attrs) { super(context, attrs);mMainHandler = new Handler(context.getMainLooper());SurfaceHolder holder = this.getHolder();holder.addCallback(mCallback);mThread = new MyDrawableThread(holder);mThread.start();}/*** 設置圖片** @param items*/public void setItem(Bitmap[] items, MyViewClickListener listener) {Log.d(TAG, "--->setItem");if (items != null) {mItems = items;}mListener = listener;}float x = 0;float y = 0;private float mBuildDegree = 0;private long time_start = 0;@Overridepublic boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d(TAG, "ACTION_DOWN");x = event.getX();y = event.getY();time_start = System.currentTimeMillis();break;case MotionEvent.ACTION_UP: {Log.d(TAG, "ACTION_UP");float dstx = event.getX();float dsty = event.getY();if ((System.currentTimeMillis() - time_start) <= TIME_CLICK_INTERVAL) {Log.d(TAG, "--->TIME_CLICK_INTERVAL");mThreadHandler.sendMessage(mThreadHandler.obtainMessage(WHAT_CLICK, (int) dstx, (int) dsty));}time_start = 0;x = 0;y = 0;break;}case MotionEvent.ACTION_MOVE:Log.d(TAG, "ACTION_MOVE");float dstx = event.getX();float dsty = event.getY();Log.d(TAG, "src x: " + x + "y: " + y);Log.d(TAG, "dst x: " + dstx + "y: " + dsty);float degree = 0;degree = (float) getActionDegrees(centerX, centerY, dstx, dsty, x,y);Log.d(TAG, "degree: " + degree);x = dstx;y = dsty;mBuildDegree -= degree;mThreadHandler.sendMessage(mThreadHandler.obtainMessage(WHAT_MOVE,mBuildDegree));break;default:break;}return true;}private class MyDrawableThread extends Thread {private SurfaceHolder mHolder;public MyDrawableThread(SurfaceHolder holder) {mHolder = holder;}@Overridepublic void run() {Log.d(TAG, "--->MyThread run");Looper.prepare();mThreadHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case WHAT_MOVE:float degree = (Float) msg.obj;drawImgByRoate(degree);break;case WHAT_CLICK:if (mListener != null && mItems != null&& mItems.length > 0 && mItems[0] != null) {int dstx = msg.arg1;int dsty = msg.arg2;Bitmap firstBitmap = mItems[0];int interval = (firstBitmap.getHeight() > firstBitmap.getWidth()) ? firstBitmap.getWidth() / 2: firstBitmap.getHeight() / 2;Log.d(TAG, "--->TIME_CLICK_INTERVAL tempdistance: "+ interval);if (mPoints != null) {for (int i = 0; i < mPoints.size(); ++i) {Point point = mPoints.get(i);double tempx = Math.abs(point.x - dstx);double tempy = Math.abs(point.y - dsty);double distance = Math.sqrt(tempx * tempx+ tempy * tempy);Log.d(TAG, "--->TIME_CLICK_INTERVAL for: "+ i + " " + distance);if (distance <= interval) {final int index = i;mMainHandler.post(new Runnable() {@Overridepublic void run() {Log.d(TAG,"--->TIME_CLICK_INTERVAL onItemClick: "+ index);mListener.onItemClick(index);}});break;}}}}break;default:super.handleMessage(msg);}}};Looper.loop();}private void drawImgByRoate(float degree) {Log.d(TAG, "mdegree>> " + degree);Canvas canvas = null;Paint paint = new Paint();int count = mItems.length;try {synchronized (mHolder) {canvas = mHolder.lockCanvas();clear(canvas);mPoints.clear();for (int i = 0; i < count; i++) {Bitmap bitmap = mItems[i];// 計算x,yfloat reaote = degree + (360 / count) * i;Log.d(TAG, i + " >> " + reaote);float x = (float) (Radius* Math.cos(Math.toRadians(reaote)) + centerX);float y = (float) (Radius* Math.sin(Math.toRadians(reaote)) + centerY);Log.d(TAG, "x>> " + x);Log.d(TAG, "y>> " + y);// drawint tempX = (int) (x - bitmap.getWidth() / 2);int tempY = (int) (y - bitmap.getHeight() / 2);mPoints.add(new Point((int) x, (int) y)); canvas.drawBitmap(bitmap, tempX, tempY, paint);}}} catch (Exception e) {e.printStackTrace();} finally {if (canvas != null) {Log.d(TAG, "--->unlockCanvasAndPost");mHolder.unlockCanvasAndPost(canvas);// 結束鎖定畫圖,并提交改變。 }}}private void clear(Canvas canvas) {Paint paint = new Paint();paint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));canvas.drawPaint(paint);paint.setXfermode(new PorterDuffXfermode(Mode.SRC));}};SurfaceHolder.Callback mCallback = new Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {// TODO Auto-generated method stubLog.d(TAG, "--->surfaceDestroyed");}@Overridepublic void surfaceCreated(SurfaceHolder holder) {// TODO Auto-generated method stubLog.d(TAG, "--->surfaceCreated");viewWidth = getWidth();viewHeight = getHeight();Radius = (viewWidth / 2) - 100;Log.d(TAG, "viewWidth: " + viewWidth);Log.d(TAG, "viewHeight: " + viewHeight);centerX = viewWidth / 2;centerY = viewHeight / 2;mThreadHandler.sendMessage(mThreadHandler.obtainMessage(WHAT_MOVE,0f));}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {Log.d(TAG, "--->surfaceChanged");}};public void release() {if (mItems != null) {for (Bitmap bitmap : mItems) {bitmap = null;}}mItems = null;mListener = null;}/*** 獲取兩點到第三點的夾角。** @param centerX* @param centerY* @param nowX* @param nowY* @param oldX* @param oldY* @return*/private double getActionDegrees(float centerX, float centerY, float nowX,float nowY, float oldX, float oldY) {double a = Math.sqrt((nowX - oldX) * (nowX - oldX) + (nowY - oldY)* (nowY - oldY));double b = Math.sqrt((centerX - oldX) * (centerX - oldX)+ (centerY - oldY) * (centerY - oldY));double c = Math.sqrt((nowX - centerX) * (nowX - centerX)+ (nowY - centerY) * (nowY - centerY));// 余弦定理double cosA = (b * b + c * c - a * a) / (2 * b * c);// 返回余弦值為指定數字的角度,Math函數為我們提供的方法double arcA = Math.acos(cosA);double degree = arcA * 180 / Math.PI;// 接下來我們要討論正負值的關系了,也就是求出是順時針還是逆時針。// 第1、2象限if (nowY < centerY && oldY < centerY) {if (nowX < centerX && oldX > centerX) {// 由2象限向1象限滑動return degree;}// 由1象限向2象限滑動else if (nowX >= centerX && oldX <= centerX) {return -degree;}}// 第3、4象限if (nowY > centerY && oldY > centerY) {// 由3象限向4象限滑動if (nowX < centerX && oldX > centerX) {return -degree;}// 由4象限向3象限滑動else if (nowX > centerX && oldX < centerX) {return degree;}}// 第2、3象限if (nowX < centerX && oldX < centerX) {// 由2象限向3象限滑動if (nowY < centerY && oldY > centerY) {return -degree;}// 由3象限向2象限滑動else if (nowY > centerY && oldY < centerY) {return degree;}}// 第1、4象限if (nowX > centerX && oldX > centerX) {// 由4向1滑動if (nowY > centerY && oldY < centerY) {return -degree;}// 由1向4滑動else if (nowY < centerY && oldY > centerY) {return degree;}}// 在特定的象限內float tanB = (nowY - centerY) / (nowX - centerX); float tanC = (oldY - centerY) / (oldX - centerX);if ((nowX > centerX && nowY > centerY && oldX > centerX&& oldY > centerY && tanB > tanC)// 第一象限|| (nowX > centerX && nowY < centerY && oldX > centerX&& oldY < centerY && tanB > tanC)// 第四象限|| (nowX < centerX && nowY < centerY && oldX < centerX&& oldY < centerY && tanB > tanC)// 第三象限|| (nowX < centerX && nowY > centerY && oldX < centerX&& oldY > centerY && tanB > tanC))// 第二象限return -degree;return degree;}public interface MyViewClickListener {public void onItemClick(int itemIndex);} }?
轉載于:https://www.cnblogs.com/afluy/p/4324430.html
總結
以上是生活随笔為你收集整理的【Android】自定义环形菜单View的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CPU的三级缓存的作用介绍
- 下一篇: 非mapreduce生成Hfile,然后