zoukankan      html  css  js  c++  java
  • Android 手势锁的实现 为了让自己的应用程序的安全,现在

    转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/36236113

    今天偶遇以github上gesturelock关于手势锁的一个样例(有兴趣的去搜索下看看),于是下载下来研究,无奈基本没有凝视。代码上存在一些问题(当设置gravity=center_vertical无法进行手势选择,无意中发现的),于是借鉴这位仁兄的代码。自己重写写了一个,修复了一些问题,增加一些主要的自己定义属性。在此先感谢这位兄弟~。

    先上图。默认效果图:



    当然能够自己定义数量啊,颜色神马的。自己定义效果图:



    假设你有艺术细胞,能够给我推荐几个颜色,无奈个人审美有问题~


    1、总体思路

    a、自己定义了一个RelativeLayout(GestureLockViewGroup)在里面会依据传入的每行的个数,生成多个GestureLockView(就是上面一个个小圈圈),然后会自己主动进行布局,里面的宽度,间距。内圆的直径。箭头的大小神马的都是百分比实现的。所以大胆的设置你喜欢的个数,仅仅要你没有密集恐惧症~

    b、GestureLockView有三个状态。没有手指触碰、手指触碰、和手指抬起。会依据这三个状态绘制不同的效果,以及抬起时的小箭头须要旋转的角度,会依据用户选择的GestureLockView,进行计算。在GestureLockViewGroup为每一个GestureLockView设置

    c、GestureLockViewGroup主要就是推断用户ACTION_MOVE。ACTION_DOWN 。 ACTION_UP时改变选中的GestureLockView的状态。而且记录下来,提供一定的回调。

    以下開始看代码:

    2、声明一些用户能够设置的属性:

    <?xml version="1.0" encoding="utf-8"?

    > <resources> <attr name="color_no_finger_inner_circle" format="color" /> <attr name="color_no_finger_outer_circle" format="color" /> <attr name="color_finger_on" format="color" /> <attr name="color_finger_up" format="color" /> <attr name="count" format="integer" /> <attr name="tryTimes" format="integer" /> <declare-styleable name="GestureLockViewGroup"> <attr name="color_no_finger_inner_circle" /> <attr name="color_no_finger_outer_circle" /> <attr name="color_finger_on" /> <attr name="color_finger_up" /> <attr name="count" /> <attr name="tryTimes" /> </declare-styleable> </resources>


    用户能够用过在xml文件里设置这些属性,改变外观,最多尝试次数以及数量等。

    3、GestureLockView

    package com.zhy.zhy_gesturelockview.view;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.graphics.Path;
    import android.view.View;
    
    public class GestureLockView extends View
    {
    	private static final String TAG = "GestureLockView";
    	/**
    	 * GestureLockView的三种状态
    	 */
    	enum Mode
    	{
    		STATUS_NO_FINGER, STATUS_FINGER_ON, STATUS_FINGER_UP;
    	}
    
    	/**
    	 * GestureLockView的当前状态
    	 */
    	private Mode mCurrentStatus = Mode.STATUS_NO_FINGER;
    	
    	/**
    	 * 宽度
    	 */
    	private int mWidth;
    	/**
    	 * 高度
    	 */
    	private int mHeight;
    	/**
    	 * 外圆半径
    	 */
    	private int mRadius;
    	/**
    	 * 画笔的宽度
    	 */
    	private int mStrokeWidth = 2;
    
    	/**
    	 * 圆心坐标
    	 */
    	private int mCenterX;
    	private int mCenterY;
    	private Paint mPaint;
    
    	/**
    	 * 箭头(小三角最长边的一半长度 = mArrawRate * mWidth / 2 )
    	 */
    	private float mArrowRate = 0.333f;
    	private int mArrowDegree = -1;
    	private Path mArrowPath;
    	/**
    	 * 内圆的半径 = mInnerCircleRadiusRate * mRadus
    	 * 
    	 */
    	private float mInnerCircleRadiusRate = 0.3F;
    
    	/**
    	 * 四个颜色,可由用户自己定义,初始化时由GestureLockViewGroup传入
    	 */
    	private int mColorNoFingerInner;
    	private int mColorNoFingerOutter;
    	private int mColorFingerOn;
    	private int mColorFingerUp;
    
    	public GestureLockView(Context context , int colorNoFingerInner , int colorNoFingerOutter , int colorFingerOn , int colorFingerUp )
    	{
    		super(context);
    		this.mColorNoFingerInner = colorNoFingerInner;
    		this.mColorNoFingerOutter = colorNoFingerOutter;
    		this.mColorFingerOn = colorFingerOn;
    		this.mColorFingerUp = colorFingerUp;
    		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    		mArrowPath = new Path();
    
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    	{
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    		mWidth = MeasureSpec.getSize(widthMeasureSpec);
    		mHeight = MeasureSpec.getSize(heightMeasureSpec);
    
    		// 取长和宽中的小值
    		mWidth = mWidth < mHeight ? mWidth : mHeight;
    		mRadius = mCenterX = mCenterY = mWidth / 2;
    		mRadius -= mStrokeWidth / 2;
    
    		// 绘制三角形,初始时是个默认箭头朝上的一个等腰三角形,用户绘制结束后,依据由两个GestureLockView决定须要旋转多少度
    		float mArrowLength = mWidth / 2 * mArrowRate;
    		mArrowPath.moveTo(mWidth / 2, mStrokeWidth + 2);
    		mArrowPath.lineTo(mWidth / 2 - mArrowLength, mStrokeWidth + 2
    				+ mArrowLength);
    		mArrowPath.lineTo(mWidth / 2 + mArrowLength, mStrokeWidth + 2
    				+ mArrowLength);
    		mArrowPath.close();
    		mArrowPath.setFillType(Path.FillType.WINDING);
    
    	}
    
    	@Override
    	protected void onDraw(Canvas canvas)
    	{
    
    		switch (mCurrentStatus)
    		{
    		case STATUS_FINGER_ON:
    
    			// 绘制外圆
    			mPaint.setStyle(Style.STROKE);
    			mPaint.setColor(mColorFingerOn);
    			mPaint.setStrokeWidth(2);
    			canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
    			// 绘制内圆
    			mPaint.setStyle(Style.FILL);
    			canvas.drawCircle(mCenterX, mCenterY, mRadius
    					* mInnerCircleRadiusRate, mPaint);
    			break;
    		case STATUS_FINGER_UP:
    			// 绘制外圆
    			mPaint.setColor(mColorFingerUp);
    			mPaint.setStyle(Style.STROKE);
    			mPaint.setStrokeWidth(2);
    			canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
    			// 绘制内圆
    			mPaint.setStyle(Style.FILL);
    			canvas.drawCircle(mCenterX, mCenterY, mRadius
    					* mInnerCircleRadiusRate, mPaint);
    
    			drawArrow(canvas);
    
    			break;
    
    		case STATUS_NO_FINGER:
    
    			// 绘制外圆
    			mPaint.setStyle(Style.FILL);
    			mPaint.setColor(mColorNoFingerOutter);
    			canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
    			// 绘制内圆
    			mPaint.setColor(mColorNoFingerInner);
    			canvas.drawCircle(mCenterX, mCenterY, mRadius
    					* mInnerCircleRadiusRate, mPaint);
    			break;
    
    		}
    
    	}
    
    	/**
    	 * 绘制箭头
    	 * @param canvas
    	 */
    	private void drawArrow(Canvas canvas)
    	{
    		if (mArrowDegree != -1)
    		{
    			mPaint.setStyle(Paint.Style.FILL);
    
    			canvas.save();
    			canvas.rotate(mArrowDegree, mCenterX, mCenterY);
    			canvas.drawPath(mArrowPath, mPaint);
    
    			canvas.restore();
    		}
    
    	}
    
    	/**
    	 * 设置当前模式并重绘界面
    	 * 
    	 * @param mode
    	 */
    	public void setMode(Mode mode)
    	{
    		this.mCurrentStatus = mode;
    		invalidate();
    	}
    
    	public void setArrowDegree(int degree)
    	{
    		this.mArrowDegree = degree;
    	}
    
    	public int getArrowDegree()
    	{
    		return this.mArrowDegree;
    	}
    }
    

    凝视非常具体,主要就是onDraw时。推断当前状态。绘制不同的显示效果。状态的改变都是GestureLockViewGroup的onTouchEvent中设置的。

    4、GestureLockViewGroup

    package com.zhy.zhy_gesturelockview.view;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.Point;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.RelativeLayout;
    
    import com.zhy.zhy_gesturelockview.R;
    import com.zhy.zhy_gesturelockview.view.GestureLockView.Mode;
    
    /**
     * 总体包括n*n个GestureLockView,每一个GestureLockView间间隔mMarginBetweenLockView,
     * 最外层的GestureLockView与容器存在mMarginBetweenLockView的外边距
     * 
     * 关于GestureLockView的边长(n*n): n * mGestureLockViewWidth + ( n + 1 ) *
     * mMarginBetweenLockView = mWidth ; 得:mGestureLockViewWidth = 4 * mWidth / ( 5
     * * mCount + 1 ) 注:mMarginBetweenLockView = mGestureLockViewWidth * 0.25 ;
     * 
     * @author zhy
     * 
     */
    public class GestureLockViewGroup extends RelativeLayout
    {
    
    	private static final String TAG = "GestureLockViewGroup";
    	/**
    	 * 保存全部的GestureLockView
    	 */
    	private GestureLockView[] mGestureLockViews;
    	/**
    	 * 每一个边上的GestureLockView的个数
    	 */
    	private int mCount = 4;
    	/**
    	 * 存储答案
    	 */
    	private int[] mAnswer = { 0, 1, 2, 5, 8 };
    	/**
    	 * 保存用户选中的GestureLockView的id
    	 */
    	private List<Integer> mChoose = new ArrayList<Integer>();
    
    	private Paint mPaint;
    	/**
    	 * 每一个GestureLockView中间的间距 设置为:mGestureLockViewWidth * 25%
    	 */
    	private int mMarginBetweenLockView = 30;
    	/**
    	 * GestureLockView的边长 4 * mWidth / ( 5 * mCount + 1 )
    	 */
    	private int mGestureLockViewWidth;
    
    	/**
    	 * GestureLockView无手指触摸的状态下内圆的颜色
    	 */
    	private int mNoFingerInnerCircleColor = 0xFF939090;
    	/**
    	 * GestureLockView无手指触摸的状态下外圆的颜色
    	 */
    	private int mNoFingerOuterCircleColor = 0xFFE0DBDB;
    	/**
    	 * GestureLockView手指触摸的状态下内圆和外圆的颜色
    	 */
    	private int mFingerOnColor = 0xFF378FC9;
    	/**
    	 * GestureLockView手指抬起的状态下内圆和外圆的颜色
    	 */
    	private int mFingerUpColor = 0xFFFF0000;
    
    	/**
    	 * 宽度
    	 */
    	private int mWidth;
    	/**
    	 * 高度
    	 */
    	private int mHeight;
    
    	private Path mPath;
    	/**
    	 * 指引线的開始位置x
    	 */
    	private int mLastPathX;
    	/**
    	 * 指引线的開始位置y
    	 */
    	private int mLastPathY;
    	/**
    	 * 指引下的结束位置
    	 */
    	private Point mTmpTarget = new Point();
    
    	/**
    	 * 最大尝试次数
    	 */
    	private int mTryTimes = 4;
    	/**
    	 * 回调接口
    	 */
    	private OnGestureLockViewListener mOnGestureLockViewListener;
    
    	public GestureLockViewGroup(Context context, AttributeSet attrs)
    	{
    		this(context, attrs, 0);
    	}
    
    	public GestureLockViewGroup(Context context, AttributeSet attrs,
    			int defStyle)
    	{
    		super(context, attrs, defStyle);
    		/**
    		 * 获得全部自己定义的參数的值
    		 */
    		TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
    				R.styleable.GestureLockViewGroup, defStyle, 0);
    		int n = a.getIndexCount();
    
    		for (int i = 0; i < n; i++)
    		{
    			int attr = a.getIndex(i);
    			switch (attr)
    			{
    			case R.styleable.GestureLockViewGroup_color_no_finger_inner_circle:
    				mNoFingerInnerCircleColor = a.getColor(attr,
    						mNoFingerInnerCircleColor);
    				break;
    			case R.styleable.GestureLockViewGroup_color_no_finger_outer_circle:
    				mNoFingerOuterCircleColor = a.getColor(attr,
    						mNoFingerOuterCircleColor);
    				break;
    			case R.styleable.GestureLockViewGroup_color_finger_on:
    				mFingerOnColor = a.getColor(attr, mFingerOnColor);
    				break;
    			case R.styleable.GestureLockViewGroup_color_finger_up:
    				mFingerUpColor = a.getColor(attr, mFingerUpColor);
    				break;
    			case R.styleable.GestureLockViewGroup_count:
    				mCount = a.getInt(attr, 3);
    				break;
    			case R.styleable.GestureLockViewGroup_tryTimes:
    				mTryTimes = a.getInt(attr, 5);
    			default:
    				break;
    			}
    		}
    
    		a.recycle();
    
    		// 初始化画笔
    		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    		mPaint.setStyle(Paint.Style.STROKE);
    		// mPaint.setStrokeWidth(20);
    		mPaint.setStrokeCap(Paint.Cap.ROUND);
    		mPaint.setStrokeJoin(Paint.Join.ROUND);
    		// mPaint.setColor(Color.parseColor("#aaffffff"));
    		mPath = new Path();
    	}
    
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    	{
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    		mWidth = MeasureSpec.getSize(widthMeasureSpec);
    		mHeight = MeasureSpec.getSize(heightMeasureSpec);
    
    		// Log.e(TAG, mWidth + "");
    		// Log.e(TAG, mHeight + "");
    
    		mHeight = mWidth = mWidth < mHeight ? mWidth : mHeight;
    
    		// setMeasuredDimension(mWidth, mHeight);
    
    		// 初始化mGestureLockViews
    		if (mGestureLockViews == null)
    		{
    			mGestureLockViews = new GestureLockView[mCount * mCount];
    			// 计算每一个GestureLockView的宽度
    			mGestureLockViewWidth = (int) (4 * mWidth * 1.0f / (5 * mCount + 1));
    			//计算每一个GestureLockView的间距
    			mMarginBetweenLockView = (int) (mGestureLockViewWidth * 0.25);
    			// 设置画笔的宽度为GestureLockView的内圆直径略微小点(不喜欢的话。随便设)
    			mPaint.setStrokeWidth(mGestureLockViewWidth * 0.29f);
    
    			for (int i = 0; i < mGestureLockViews.length; i++)
    			{
    				//初始化每一个GestureLockView
    				mGestureLockViews[i] = new GestureLockView(getContext(),
    						mNoFingerInnerCircleColor, mNoFingerOuterCircleColor,
    						mFingerOnColor, mFingerUpColor);
    				mGestureLockViews[i].setId(i + 1);
    				//设置參数,主要是定位GestureLockView间的位置
    				RelativeLayout.LayoutParams lockerParams = new RelativeLayout.LayoutParams(
    						mGestureLockViewWidth, mGestureLockViewWidth);
    
    				// 不是每行的第一个。则设置位置为前一个的右边
    				if (i % mCount != 0)
    				{
    					lockerParams.addRule(RelativeLayout.RIGHT_OF,
    							mGestureLockViews[i - 1].getId());
    				}
    				// 从第二行開始。设置为上一行同一位置View的以下
    				if (i > mCount - 1)
    				{
    					lockerParams.addRule(RelativeLayout.BELOW,
    							mGestureLockViews[i - mCount].getId());
    				}
    				//设置右下左上的边距
    				int rightMargin = mMarginBetweenLockView;
    				int bottomMargin = mMarginBetweenLockView;
    				int leftMagin = 0;
    				int topMargin = 0;
    				/**
    				 * 每一个View都有右外边距和底外边距 第一行的有上外边距 第一列的有左外边距
    				 */
    				if (i >= 0 && i < mCount)// 第一行
    				{
    					topMargin = mMarginBetweenLockView;
    				}
    				if (i % mCount == 0)// 第一列
    				{
    					leftMagin = mMarginBetweenLockView;
    				}
    
    				lockerParams.setMargins(leftMagin, topMargin, rightMargin,
    						bottomMargin);
    				mGestureLockViews[i].setMode(Mode.STATUS_NO_FINGER);
    				addView(mGestureLockViews[i], lockerParams);
    			}
    
    			Log.e(TAG, "mWidth = " + mWidth + " ,  mGestureViewWidth = "
    					+ mGestureLockViewWidth + " , mMarginBetweenLockView = "
    					+ mMarginBetweenLockView);
    
    		}
    	}
    
    	@Override
    	public boolean onTouchEvent(MotionEvent event)
    	{
    		int action = event.getAction();
    		int x = (int) event.getX();
    		int y = (int) event.getY();
    
    		switch (action)
    		{
    		case MotionEvent.ACTION_DOWN:
    			// 重置
    			reset();
    			break;
    		case MotionEvent.ACTION_MOVE:
    			mPaint.setColor(mFingerOnColor);
    			mPaint.setAlpha(50);
    			GestureLockView child = getChildIdByPos(x, y);
    			if (child != null)
    			{
    				int cId = child.getId();
    				if (!mChoose.contains(cId))
    				{
    					mChoose.add(cId);
    					child.setMode(Mode.STATUS_FINGER_ON);
    					if (mOnGestureLockViewListener != null)
    						mOnGestureLockViewListener.onBlockSelected(cId);
    					// 设置指引线的起点
    					mLastPathX = child.getLeft() / 2 + child.getRight() / 2;
    					mLastPathY = child.getTop() / 2 + child.getBottom() / 2;
    
    					if (mChoose.size() == 1)// 当前加入为第一个
    					{
    						mPath.moveTo(mLastPathX, mLastPathY);
    					} else
    					// 非第一个,将两者使用线连上
    					{
    						mPath.lineTo(mLastPathX, mLastPathY);
    					}
    
    				}
    			}
    			// 指引线的终点
    			mTmpTarget.x = x;
    			mTmpTarget.y = y;
    			break;
    		case MotionEvent.ACTION_UP:
    
    			mPaint.setColor(mFingerUpColor);
    			mPaint.setAlpha(50);
    			this.mTryTimes--;
    
    			// 回调是否成功
    			if (mOnGestureLockViewListener != null && mChoose.size() > 0)
    			{
    				mOnGestureLockViewListener.onGestureEvent(checkAnswer());
    				if (this.mTryTimes == 0)
    				{
    					mOnGestureLockViewListener.onUnmatchedExceedBoundary();
    				}
    			}
    
    			Log.e(TAG, "mUnMatchExceedBoundary = " + mTryTimes);
    			Log.e(TAG, "mChoose = " + mChoose);
    			// 将终点设置位置为起点。即取消指引线
    			mTmpTarget.x = mLastPathX;
    			mTmpTarget.y = mLastPathY;
    
    			// 改变子元素的状态为UP
    			changeItemMode();
    			
    			// 计算每一个元素中箭头须要旋转的角度
    			for (int i = 0; i + 1 < mChoose.size(); i++)
    			{
    				int childId = mChoose.get(i);
    				int nextChildId = mChoose.get(i + 1);
    
    				GestureLockView startChild = (GestureLockView) findViewById(childId);
    				GestureLockView nextChild = (GestureLockView) findViewById(nextChildId);
    
    				int dx = nextChild.getLeft() - startChild.getLeft();
    				int dy = nextChild.getTop() - startChild.getTop();
    				// 计算角度
    				int angle = (int) Math.toDegrees(Math.atan2(dy, dx)) + 90;
    				startChild.setArrowDegree(angle);
    			}
    			break;
    
    		}
    		invalidate();
    		return true;
    	}
    
    	private void changeItemMode()
    	{
    		for (GestureLockView gestureLockView : mGestureLockViews)
    		{
    			if (mChoose.contains(gestureLockView.getId()))
    			{
    				gestureLockView.setMode(Mode.STATUS_FINGER_UP);
    			}
    		}
    	}
    
    	/**
    	 * 
    	 * 做一些必要的重置
    	 */
    	private void reset()
    	{
    		mChoose.clear();
    		mPath.reset();
    		for (GestureLockView gestureLockView : mGestureLockViews)
    		{
    			gestureLockView.setMode(Mode.STATUS_NO_FINGER);
    			gestureLockView.setArrowDegree(-1);
    		}
    	}
    	/**
    	 * 检查用户绘制的手势是否正确
    	 * @return
    	 */
    	private boolean checkAnswer()
    	{
    		if (mAnswer.length != mChoose.size())
    			return false;
    
    		for (int i = 0; i < mAnswer.length; i++)
    		{
    			if (mAnswer[i] != mChoose.get(i))
    				return false;
    		}
    
    		return true;
    	}
    	
    	/**
    	 * 检查当前左边是否在child中
    	 * @param child
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	private boolean checkPositionInChild(View child, int x, int y)
    	{
    
    		//设置了内边距,即x,y必须落入下GestureLockView的内部中间的小区域中,能够通过调整padding使得x,y落入范围不变大。或者不设置padding
    		int padding = (int) (mGestureLockViewWidth * 0.15);
    
    		if (x >= child.getLeft() + padding && x <= child.getRight() - padding
    				&& y >= child.getTop() + padding
    				&& y <= child.getBottom() - padding)
    		{
    			return true;
    		}
    		return false;
    	}
    
    	/**
    	 * 通过x,y获得落入的GestureLockView
    	 * @param x
    	 * @param y
    	 * @return
    	 */
    	private GestureLockView getChildIdByPos(int x, int y)
    	{
    		for (GestureLockView gestureLockView : mGestureLockViews)
    		{
    			if (checkPositionInChild(gestureLockView, x, y))
    			{
    				return gestureLockView;
    			}
    		}
    
    		return null;
    
    	}
    
    	/**
    	 * 设置回调接口
    	 * 
    	 * @param listener
    	 */
    	public void setOnGestureLockViewListener(OnGestureLockViewListener listener)
    	{
    		this.mOnGestureLockViewListener = listener;
    	}
    
    	/**
    	 * 对外发布设置答案的方法
    	 * 
    	 * @param answer
    	 */
    	public void setAnswer(int[] answer)
    	{
    		this.mAnswer = answer;
    	}
    
    	/**
    	 * 设置最大实验次数
    	 * 
    	 * @param boundary
    	 */
    	public void setUnMatchExceedBoundary(int boundary)
    	{
    		this.mTryTimes = boundary;
    	}
    
    	@Override
    	public void dispatchDraw(Canvas canvas)
    	{
    		super.dispatchDraw(canvas);
    		//绘制GestureLockView间的连线
    		if (mPath != null)
    		{
    			canvas.drawPath(mPath, mPaint);
    		}
    		//绘制指引线
    		if (mChoose.size() > 0)
    		{
    			if (mLastPathX != 0 && mLastPathY != 0)
    				canvas.drawLine(mLastPathX, mLastPathY, mTmpTarget.x,
    						mTmpTarget.y, mPaint);
    		}
    
    	}
    
    	public interface OnGestureLockViewListener
    	{
    		/**
    		 * 单独选中元素的Id
    		 * 
    		 * @param position
    		 */
    		public void onBlockSelected(int cId);
    
    		/**
    		 * 是否匹配
    		 * 
    		 * @param matched
    		 */
    		public void onGestureEvent(boolean matched);
    
    		/**
    		 * 超过尝试次数
    		 */
    		public void onUnmatchedExceedBoundary();
    	}
    }
    

    凝视极其具体。用极其只是分~主要就是onTouchEvent中对用户选择的GestureLockView进行推断,以及改变GestureLockView状态等。

    5、布局文件

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:zhy="http://schemas.android.com/apk/res/com.zhy.zhy_gesturelockview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <com.zhy.zhy_gesturelockview.view.GestureLockViewGroup
            android:id="@+id/id_gestureLockViewGroup"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#F2F2F7"
            android:gravity="center_vertical"
            zhy:count="3"
            zhy:tryTimes="5" />
    <!--   zhy:color_no_finger_inner_circle="#ff085D58"
            zhy:color_no_finger_outer_circle="#ff08F0E0"
            zhy:color_finger_on="#FF1734BF" -->
    
    </RelativeLayout>

    有兴趣的能够自己定义属性,把凝视的代码添进去即可,当然你也能够什么都不设置,单纯设置宽度和高度,我认为默认效果也是不错的 ~

    6、调用

    package com.zhy.zhy_gesturelockview;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.Toast;
    
    import com.zhy.zhy_gesturelockview.view.GestureLockViewGroup;
    import com.zhy.zhy_gesturelockview.view.GestureLockViewGroup.OnGestureLockViewListener;
    
    public class MainActivity extends Activity
    {
    
    	private GestureLockViewGroup mGestureLockViewGroup;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState)
    	{
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    
    		mGestureLockViewGroup = (GestureLockViewGroup) findViewById(R.id.id_gestureLockViewGroup);
    		mGestureLockViewGroup.setAnswer(new int[] { 1, 2, 3, 4,5 });
    		mGestureLockViewGroup
    				.setOnGestureLockViewListener(new OnGestureLockViewListener()
    				{
    
    					@Override
    					public void onUnmatchedExceedBoundary()
    					{
    						Toast.makeText(MainActivity.this, "错误5次...",
    								Toast.LENGTH_SHORT).show();
    						mGestureLockViewGroup.setUnMatchExceedBoundary(5);
    					}
    
    					@Override
    					public void onGestureEvent(boolean matched)
    					{
    						Toast.makeText(MainActivity.this, matched+"",
    								Toast.LENGTH_SHORT).show();
    					}
    
    					@Override
    					public void onBlockSelected(int cId)
    					{
    					}
    				});
    	}
    
    }
    

    调用是不是so easy。懒得看代码又须要用的,能够直接拿来使用。等哪天闲着蛋疼能够研究研究代码~


    ok,有不论什么问题的留言~


    源代码明天到公司贴出来吧。尼玛,这是拿手机共享的热点写的,我的流量啊~~~~还好是1号~

    源代码点击下载




    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    leetcode 279. Perfect Squares
    leetcode 546. Remove Boxes
    leetcode 312. Burst Balloons
    leetcode 160. Intersection of Two Linked Lists
    leetcode 55. Jump Game
    剑指offer 滑动窗口的最大值
    剑指offer 剪绳子
    剑指offer 字符流中第一个不重复的字符
    leetcode 673. Number of Longest Increasing Subsequence
    leetcode 75. Sort Colors (荷兰三色旗问题)
  • 原文地址:https://www.cnblogs.com/hrhguanli/p/4804938.html
Copyright © 2011-2022 走看看