zoukankan      html  css  js  c++  java
  • 自己定义九宫格手势解锁

    项目中用到手势解锁,然而没有在GitHub上找到想要的样式= =,仅仅好自己来定义了。以下来看代码~~

    基本上非常多应用的手势解锁全都是九宫格的,内部内就是九个小圈圈而已。

    那么我们就先来自己定义这个小圈圈吧~

    圈圈的颜色选择状态有大致有三种状态。所以我定义了一个枚举来区分

    package com.juzisang.com.library;
    
    /**
     * Created by 橘子桑 on 2016/3/27.
     */
    public enum LockState {
        SELECT_STATE,//选中
        ERRER_STATE, //错误
        DEFAULT_COLOR //默认
    }
    

    圈圈分为边框。内部填充色。还有内部圆。所以我定义了三个画笔来区分。

    package com.juzisang.com.library;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * Created by 橘子桑 on 2016/3/27.
     */
    public class MarkerView extends View {
        //是否显示内部的圈圈
        private boolean mInsideNodeShow;
        //宽度
        protected int mContentWidth;
        //宽度
        protected int mContentRadius;
        //选中状态
        protected LockState mCurrentState = LockState.DEFAULT_COLOR;
        //画边框画圆的的画笔
        private Paint mNodeFramePaint;
        private Paint mNodeCirclePaint;
        private Paint mNodeFullPaint;
        //默认的颜色
        private int mDefaultColor = Color.parseColor("#757575");
        private int mDefailtFullColor = Color.parseColor("#64757575");
        private int mNodeDefaultColor = Color.parseColor("#757575");
        //选中的颜色
        private int mSelectColor = Color.parseColor("#7ECEF4");
        private int mFrameSelectFullColor = Color.parseColor("#647ECEF4");
        private int mNodeSelectColor = Color.parseColor("#7ECEF4");
        //错误时候的颜色
        private int mErrerColor = Color.parseColor("#EC6941");
        private int mErrerFullColor = Color.parseColor("#64EC6941");
        private int mErrerNodeColor = Color.parseColor("#EC6941");
        //边框的宽度
        private int mFrameLineWidth;
        private int mNodeRadius;
        //每一个圈圈的内边距
        private int mNodePadding;
        //触摸有效的范围
        private float mTouchRatio;
        //当前标记的位置
        private int mNum;
    
        public MarkerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context, attrs, 0);
        }
    
        public MarkerView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView(context, attrs, defStyleAttr);
        }
        //以后外部布局传来的參数
        public MarkerView(Context context, int mDefaultColor, int mDefailtFullColor, int mNodeDefaultColor,
                          int mSelectColor, int mFrameSelectFullColor, int mNodeSelectColor,
                          int mErrerColor, int mErrerFullColor, int mErrerNodeColor,
                          int mFrameLineWidth, int mNodeRadius, int mNodePadding, boolean insideNodeShow) {
            super(context);
            this.mInsideNodeShow = insideNodeShow;
            this.mDefaultColor = mDefaultColor;
            this.mDefailtFullColor = mDefailtFullColor;
            this.mNodeDefaultColor = mNodeDefaultColor;
            this.mSelectColor = mSelectColor;
            this.mFrameSelectFullColor = mFrameSelectFullColor;
            this.mNodeSelectColor = mNodeSelectColor;
            this.mErrerColor = mErrerColor;
            this.mErrerFullColor = mErrerFullColor;
            this.mErrerNodeColor = mErrerNodeColor;
            this.mFrameLineWidth = mFrameLineWidth;
            this.mNodeRadius = mNodeRadius;
            this.mNodePadding = mNodePadding;
            //内边距
            setPadding(mNodePadding, mNodePadding, mNodePadding, mNodePadding);
            //外部圆
            mNodeFramePaint = new Paint();
            mNodeFramePaint.setColor(mDefaultColor);
            mNodeFramePaint.setAntiAlias(true);
            mNodeFramePaint.setStrokeWidth(mFrameLineWidth);
            mNodeFramePaint.setStyle(Paint.Style.STROKE);//仅仅画出边框
    
            //内部填充色
            mNodeFullPaint = new Paint();
            mNodeFullPaint.setColor(mDefailtFullColor);
            mNodeFullPaint.setStyle(Paint.Style.FILL);
            mNodeFullPaint.setAntiAlias(true);
    
            //内部圆
            mNodeCirclePaint = new Paint();
            mNodeCirclePaint.setColor(mNodeDefaultColor);
            mNodeCirclePaint.setStyle(Paint.Style.FILL);//填充
            mNodeCirclePaint.setAntiAlias(true);
        }
    
        //取当前透明度的百分比
        public int getFullAlpha(int color, float ratio) {
            return Color.argb((int) (Color.alpha(color) * ratio), Color.red(color), Color.green(color), Color.blue(color));
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mContentWidth = getWidth();
            mContentRadius = mContentWidth / 2 - Math.abs(getPaddingLeft()) - mFrameLineWidth / 2;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
    
            switch (mCurrentState) {
                case DEFAULT_COLOR: //默认
                    mNodeFramePaint.setColor(mDefaultColor);
                    mNodeFullPaint.setColor(mDefailtFullColor);
                    mNodeCirclePaint.setColor(mNodeDefaultColor);
                    //外圆
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius, mNodeFramePaint);
                    //填充色
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius - mFrameLineWidth / 2, mNodeFullPaint);
                    //中心圆
                    if (mInsideNodeShow)
                        canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mNodeRadius, mNodeCirclePaint);
                    break;
                case ERRER_STATE://错误
                    mNodeFramePaint.setColor(mErrerColor);
                    mNodeFullPaint.setColor(mErrerFullColor);
                    mNodeCirclePaint.setColor(mErrerNodeColor);
                    //外圆
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius, mNodeFramePaint);
                    //填充色
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius - mFrameLineWidth / 2, mNodeFullPaint);
                    //中心圆
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mNodeRadius, mNodeCirclePaint);
                    break;
                case SELECT_STATE://选中
                    mNodeFramePaint.setColor(mSelectColor);
                    mNodeFullPaint.setColor(mFrameSelectFullColor);
                    mNodeCirclePaint.setColor(mNodeSelectColor);
                    //外圆
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius, mNodeFramePaint);
                    //填充色
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mContentRadius - mFrameLineWidth / 2, mNodeFullPaint);
                    //中心圆
                    canvas.drawCircle(mContentWidth / 2, mContentWidth / 2, mNodeRadius, mNodeCirclePaint);
                    break;
            }
    
        }
        //设置状态,而且重绘
        public void setState(LockState CurrentState) {
            mCurrentState = CurrentState;
            invalidate();
        }
        //是否选中
        public boolean isHighLighted() {
            if (mCurrentState == LockState.SELECT_STATE || mCurrentState == LockState.ERRER_STATE) {
                return true;
            }
            return false;
        }
        //中心点X
        public int getCenterX() {
            return (getLeft() + getRight()) / 2;
        }
        //中心点Y
        public int getCenterY() {
            return (getTop() + getBottom()) / 2;
        }
        //设置圈圈在手势锁其中的位置
        protected void setNum(int num) {
            mNum = num;
        }
    
        protected int getNum() {
            return mNum;
        }
    }
    

    以上就是一个简单的圆了

    那么,自己定义View当然会有自己定义属性,所以有这么多T0T,不要问我为什么这么多属性。任性= =(事实上我还想写很多其它),自己定义属性的方法

     <!-- 线的颜色 -->
        <attr name="lineColor" format="color" />
        <!-- 线的宽度 -->
        <attr name="lineWidth" format="dimension" />
        <!--默认颜色 -->
        <attr name="defaultColor" format="color" />
        <!--默认时的填充色-->
        <attr name="defaultFullColor" format="color" />
        <!--默认内部圆颜色-->
        <attr name="defaultNodeColor" format="color" />
        <!-- ======================================================= -->
        <!-- 边框选中时边框的颜色 -->
        <attr name="selectColor" format="color" />
        <!-- 边框选中时内部的填充色 -->
        <attr name="selectFrameFullColor" format="color" />
        <!--内部圆圈选中时的颜色-->
        <attr name="selectNodeColor" format="color" />
        <!-- ======================================================= -->
        <!-- 错误的颜色 -->
        <attr name="errorColor" format="color" />
        <!--错误时内部的填充色-->
        <attr name="errorFullColor" format="color" />
        <!-- 错误时的颜色 -->
        <attr name="errorNodeColor" format="color" />
        <!-- ======================================================= -->
        <!--边框的的宽度-->
        <attr name="frameLineWidth" format="dimension" />
        <!-- 内部圆圈的宽度 -->
        <attr name="nodeRadius" format="dimension" />
        <!--内边距-->
        <attr name="nodePadding" format="dimension" />
        <!--触摸有效的比例-->
        <attr name="touchRatio" format="float" />
        <!-- 是否显示内部的圆圈 -->
        <attr name="insideNodeShow" format="boolean"/>

    LockView的代码

    package com.juzisang.com.library;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.ViewGroup;
    
    import java.util.ArrayList;
    
    /**
     * Created by 橘子桑 on 2016/3/27.
     */
    public class LockView extends ViewGroup {
        //画连接线的画笔
        private Paint mLinePaint;
        //能够触摸的区域百分比
        private float mTouchRatio;
        //线的颜色
        protected int mLineColor;
        //先的宽度
        protected float mLineWidth;
        //已经选中了的View
        ArrayList<MarkerView> mNodeViews = new ArrayList<>();
        //存储password
        protected StringBuilder pawBuilder = new StringBuilder();
        //当前手指触摸的x坐标
        protected float x;
        //当前手指触摸的y坐标
        protected float y;
        //回调
        private onLockCallback mOnLockCallback;
    
        protected int mDefaultColor;
    
        protected int mSelectColor;
    
        protected int mErrerColor;
    
        //禁用手势锁
        private boolean mLockScreen;
    
        private boolean isTouch;
    
        //是否把连接线绘制在子View的上面
        private boolean mLineTop = false;
        //手指离开马上重绘
        private boolean mFingerLeaveRedraw = true;
    
        public LockView(Context context) {
            this(context, null);
        }
    
        public LockView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public LockView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView(context, attrs, defStyleAttr);
        }
    
        protected void initView(Context context, AttributeSet attrs, int defStyleAttr) {
    
            TypedArray r = context.obtainStyledAttributes(attrs, R.styleable.MarkerView);
    
            boolean insideNodeShow = r.getBoolean(R.styleable.LockView_insideNodeShow, false);
            //默认的颜色
            mDefaultColor = r.getColor(R.styleable.LockView_defaultColor, context.getResources().getColor(android.R.color.holo_blue_dark));
            int mDefailtFullColor = r.getColor(R.styleable.LockView_defaultFullColor, getFullAlpha(mDefaultColor, 0.3F));
            int mNodeDefaultColor = (int) r.getColor(R.styleable.LockView_defaultNodeColor, mDefaultColor);
            //选中的颜色
            mSelectColor = (int) r.getColor(R.styleable.LockView_selectColor, context.getResources().getColor(android.R.color.holo_blue_light));
            int mFrameSelectFullColor = r.getColor(R.styleable.LockView_selectFrameFullColor, getFullAlpha(mSelectColor, 0.3F));
            int mNodeSelectColor = r.getColor(R.styleable.LockView_selectNodeColor, mSelectColor);
            //错误时候的颜色
            mErrerColor = r.getColor(R.styleable.LockView_errorColor, context.getResources().getColor(android.R.color.holo_red_light));
            int mErrerFullColor = r.getColor(R.styleable.LockView_errorFullColor, getFullAlpha(mErrerColor, 0.3F));
            int mErrerNodeColor = r.getColor(R.styleable.LockView_errorNodeColor, mErrerColor);
            //圆框变的宽度
            int mFrameLineWidth = (int) r.getDimension(R.styleable.LockView_frameLineWidth, DensityUtils.dip2px(context, 5));
            //内圆的直径
            int mNodeRadius = (int) r.getDimension(R.styleable.LockView_nodeRadius, DensityUtils.dip2px(context, 5));
            //内边距
            int mNodePadding = (int) r.getDimension(R.styleable.LockView_nodePadding, DensityUtils.dip2px(context, 10));
            //触摸有效区域
            mTouchRatio = r.getFloat(R.styleable.LockView_touchRatio, mTouchRatio);
            mLineColor = r.getColor(R.styleable.LockView_lineColor, mDefaultColor);
            mLineWidth = r.getDimension(R.styleable.LockView_lineWidth, DensityUtils.dip2px(context, 5));
            r.recycle();
            //设置线的颜色
            mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mLinePaint.setColor(mLineColor);
            mLinePaint.setStyle(Paint.Style.STROKE);
            mLinePaint.setStrokeWidth(mLineWidth);
            mLinePaint.setStrokeCap(Paint.Cap.ROUND);
            mLinePaint.setStrokeJoin(Paint.Join.ROUND);
    
            for (int i = 0; i < 9; i++) {
                MarkerView view = new MarkerView(context, mDefaultColor, mDefailtFullColor, mNodeDefaultColor, mSelectColor, mFrameSelectFullColor, mNodeSelectColor,
                        mErrerColor, mErrerFullColor, mErrerNodeColor, mFrameLineWidth, mNodeRadius, mNodePadding, insideNodeShow);
                view.setNum(i + 1);
                ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
                view.setLayoutParams(params);
                addView(view);
            }
    
            // 清除FLAG,否则 onDraw() 不会调用。原因是 ViewGroup 默认透明背景不须要调用 onDraw()
            setWillNotDraw(false);
    
        }
    
        public int getFullAlpha(int color, float ratio) {
            return Color.argb((int) (Color.alpha(color) * ratio), Color.red(color), Color.green(color), Color.blue(color));
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int size = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); // 測量宽度
            setMeasuredDimension(size, size);
            for (int i = 0; i < getChildCount(); i++) {
                measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
            }
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            if (changed) {
                float areaWidth = (r - l - getPaddingLeft() * 2) / 3;
                for (int n = 0; n < 9; n++) {
                    MarkerView node = (MarkerView) getChildAt(n);
                    // 获取3*3宫格内坐标
                    int row = n / 3;
                    int col = n % 3;
                    //加上内间距
                    int left = (int) (getPaddingLeft() + col * areaWidth);
                    int top = (int) (getPaddingTop() + row * areaWidth);
                    int right = (int) (left + areaWidth);
                    int bottom = (int) (top + areaWidth);
                    node.layout(left, top, right, bottom);
                }
            }
        }
    
        /**
         * 设置连接线是否绘制在子View的上面
         * true 绘制在子View的上面
         * false 绘制在子View的以下
         *
         * @param isLineTop 设置连接线是否绘制在子View的上面
         */
        public void setLineTop(boolean isLineTop) {
            mLineTop = isLineTop;
            invalidate();
        }
    
        /**
         * 设置连接线是否绘制在子View的上面
         * true 绘制在子View的上面
         * false 绘制在子View的以下
         */
        public boolean getLineTop() {
            return mLineTop;
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
    
            if (getLockScreen()) {
                invalidate();
                return false;
            }
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //恢复默认
                    resetDefault();
                    x = event.getX();
                    y = event.getY();
                    isTouch = true;
                    break;
                case MotionEvent.ACTION_MOVE:
                    x = event.getX(); // 这里要实时记录手指的坐标
                    y = event.getY();
                    MarkerView nodeView = getNodeAt(x, y);
                    //没有选中
                    if (nodeView != null && !nodeView.isHighLighted()) {
                        nodeView.setState(LockState.SELECT_STATE);
                        mNodeViews.add(nodeView);
                        //进度
                        if (mOnLockCallback != null) {
                            pawBuilder.setLength(0);
                            for (MarkerView markerView : mNodeViews) {
                                pawBuilder.append(markerView.getNum());
                            }
                            mOnLockCallback.onProgress(pawBuilder.toString(), nodeView.getNum());
                        }
                    }
                    if (mNodeViews.size() > 0) {
                        invalidate();
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    LogUtils.i("手指抬起了");
                    isTouch = false;
                    pawBuilder.setLength(0);
                    if (mNodeViews.size() <= 0) return true;
                    pawBuilder.delete(0, pawBuilder.length());
                    if (mOnLockCallback != null) {
                        for (MarkerView markerView : mNodeViews) {
                            pawBuilder.append(markerView.getNum());
                        }
                        mOnLockCallback.onFinish(pawBuilder.toString());
                    }
                    if (mFingerLeaveRedraw) {
                        resetDefault();
                    } else {
                        invalidate();
                    }
                    break;
            }
            return true;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            //线画在子view的以下
            if (!mLineTop) onDrawLock(canvas);
        }
    
        //画子View的地方
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            //放在这里的原因是。线会被子View挡到
            if (mLineTop) onDrawLock(canvas);
        }
    
        /**
         * 绘图的方法
         */
        private void onDrawLock(Canvas canvas) {
            //屏幕锁住了,仅仅画起点到终点的
            if (getLockScreen()) {
                onDrawNodeViewLock(canvas);
                return;
            }
            if (isTouch || mFingerLeaveRedraw) {
                //从第一个和最后一个的连接线
                onDrawNodeViewLock(canvas);
                //最后一个点,到手指之间的线
                if (mNodeViews.size() > 0) {
                    MarkerView lastNode = mNodeViews.get(mNodeViews.size() - 1);
                    canvas.drawLine(lastNode.getCenterX(), lastNode.getCenterY(), x, y, mLinePaint);
                }
            } else {
                //假设手指离开屏幕。而且设置了手指离开马上重绘
                onDrawNodeViewLock(canvas);
            }
    
    
        }
    
        private void onDrawNodeViewLock(Canvas canvas) {
            //从第一个和最后一个的连接线
            for (int i = 1; i < mNodeViews.size(); i++) {
                MarkerView frontNode = mNodeViews.get(i - 1);
                MarkerView backNode = mNodeViews.get(i);
                canvas.drawLine(frontNode.getCenterX(), frontNode.getCenterY(), backNode.getCenterX(), backNode.getCenterY(), mLinePaint);
            }
        }
    
        /**
         * 获取给定坐标点的Node,返回null表示当前手指在两个Node之间
         */
        private MarkerView getNodeAt(float x, float y) {
            for (int n = 0; n < getChildCount(); n++) {
                MarkerView node = (MarkerView) getChildAt(n);
                //计算触摸区域以外的距离
                float ratioPadding = (node.getWidth() - (node.getWidth() * mTouchRatio)) / 2;
                if (!(x >= node.getLeft() + ratioPadding && x < node.getRight() - ratioPadding)) {
                    continue;
                }
                if (!(y >= node.getTop() + ratioPadding && y < node.getBottom() - ratioPadding)) {
                    continue;
                }
                return node;
            }
            return null;
        }
    
        /**
         * 设置连接线的颜色
         *
         * @param color 颜色值
         */
        public void setLineColor(int color) {
            mLinePaint.setColor(color);
        }
    
        /**
         * 手指离开马上重绘
         */
        public void setfingerLeaveRedraw(boolean mFingerLeaveRedraw) {
            this.mFingerLeaveRedraw = mFingerLeaveRedraw;
        }
    
        public boolean getfingerLeaveRedraw() {
            return this.mFingerLeaveRedraw;
        }
    
        /**
         * 重置状态 为默认状态
         */
        public void resetDefault() {
            setState(LockState.DEFAULT_COLOR);
            mNodeViews.clear();
        }
    
        /**
         * 重置状态错误状态
         */
        public void resetErrer() {
            setState(LockState.ERRER_STATE);
        }
    
        /**
         * 重置为选中状态
         */
        public void resetSelect() {
            setState(LockState.SELECT_STATE);
        }
    
        /**
         * 锁屏,不同意触摸
         */
        public void LockScreen(boolean isScreen) {
            mLockScreen = isScreen;
        }
    
        public boolean getLockScreen() {
            return mLockScreen;
        }
    
        public void setState(LockState state) {
            switch (state) {
                case DEFAULT_COLOR:
                case SELECT_STATE:
                    setLineColor(mSelectColor);
                    break;
                case ERRER_STATE:
                    setLineColor(mErrerColor);
                    break;
            }
            int size = mNodeViews.size();
            for (int i = 0; i < size; i++) {
                mNodeViews.get(i).setState(state);
            }
            invalidate();
        }
    
        public void setLockCallback(onLockCallback lockCallback) {
            mOnLockCallback = lockCallback;
        }
        //回调
        public interface onLockCallback {
    
            void onProgress(String paw, int current);
    
            void onFinish(String paw);
        }
    }
    

    以上凝视都写的非常清晰了。以下讲一下遇到的一些问题。

    1.画出来的线被上面的圈圈覆盖了。

    通过百度。知道ViewGroup的onDraw是画布局中的内容的,画子View的的方法在这种方法的后面运行。所以ViewGroup的内容会被子View覆盖。那么怎么才干把连接线画在子View的上面呢,非常easy
    仅仅要在画子View的方法中运行就好了

    //画子View的地方
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            //放在这里的原因是。线会被子View挡到
            if (mLineTop) onDrawLock(canvas);
        }

    以下是View的draw()方法

     @CallSuper
        public void draw(Canvas canvas) {
            final int privateFlags = mPrivateFlags;
            final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
                    (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
            mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
    
            // Step 1, draw the background, if needed
            int saveCount;
    
            if (!dirtyOpaque) {
                drawBackground(canvas);
            }
    
            // skip step 2 & 5 if possible (common case)
            final int viewFlags = mViewFlags;
            boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
            boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
            if (!verticalEdges && !horizontalEdges) {
                // Step 3, draw the content
                if (!dirtyOpaque) onDraw(canvas);
    
                // Step 4, draw the children
                //这里就是画子View的方法了
                dispatchDraw(canvas);
    
                // Overlay is part of the content and draws beneath Foreground
                if (mOverlay != null && !mOverlay.isEmpty()) {
                    mOverlay.getOverlayView().dispatchDraw(canvas);
                }
    
                // Step 6, draw decorations (foreground, scrollbars)
                onDrawForeground(canvas);
    
                // we're done...
                return;
            }

    2.怎么设置触摸的区域?

        /**
         * 获取给定坐标点的Node,返回null表示当前手指在两个Node之间
         */
        private MarkerView getNodeAt(float x, float y) {
            for (int n = 0; n < getChildCount(); n++) {
                MarkerView node = (MarkerView) getChildAt(n);
                //计算触摸区域以外的距离
                float ratioPadding = (node.getWidth() - (node.getWidth() * mTouchRatio)) / 2;
                if (!(x >= node.getLeft() + ratioPadding && x < node.getRight() - ratioPadding)) {
                    continue;
                }
                if (!(y >= node.getTop() + ratioPadding && y < node.getBottom() - ratioPadding)) {
                    continue;
                }
                return node;
            }
            return null;
        }

    看上面代码。
    依据圆圈的宽度减去可触摸区域的长度除2。得到可触摸区域距离边框的距的距离。


    光看代码看着有点圆。画个图看一下吧
    这里写图片描写叙述

    画个图是不是清晰非常多,仅仅要用getLeft+边距。和getRight-边距,就能得到可触摸区域在x轴上的范围了。Y轴同理。不懂的同学自己用笔画一下吧~

    几乎相同就上面两个问题了
    这里写图片描写叙述

    下载地址

  • 相关阅读:
    weblogic 的应用 常见问题处理 db2 链接不上(转载)
    WebLogic简单的备份和恢复
    linux 切换用户之后变成-bash-x.x$的解决方法
    weblogic迁移随手记
    生产环境下Centos 6.5优化配置 (装载)
    查看db2表空间使用率
    Linux 之 rsyslog 系统日志转发(转载)
    windows下定时利用bat脚本实现ftp上传和下载
    rsyslog同步history日志(转载)
    linux比较指令comm、diff、grep -Ff
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7338215.html
Copyright © 2011-2022 走看看