实现的效果图:六个小图片可以跟随手指滑动绕中心点旋转

【Android】自定义环形菜单View_第1张图片

代码:

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;    @Override    public 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;        }        @Override        public 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() {                                            @Override                                            public 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,y                        float 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);                        // draw                        int 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() {        @Override        public void surfaceDestroyed(SurfaceHolder holder) {            // TODO Auto-generated method stub            Log.d(TAG, "--->surfaceDestroyed");        }        @Override        public void surfaceCreated(SurfaceHolder holder) {            // TODO Auto-generated method stub            Log.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));        }        @Override        public 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);    }}

更多相关文章

  1. android 取现在时间和以前的时间做差 求出天数 时间 和分钟数
  2. android发送post请求出现问题

随机推荐

  1. Android系统版本与API等级对应关系表
  2. Android(安卓)Studio 升级到3.4后的两个
  3. 2017android新技术总结
  4. 在 Android(安卓)应用程序中使用 Interne
  5. Android常用类库说明
  6. Android(安卓)ADB 找不到 Devices 的解决
  7. Android(安卓)Studio 导入 Android(安卓)
  8. Android软件开发学习路线规划
  9. android定制 Launcher
  10. 微信接口 - android