前言:Android有很多原生控件供开发者使用,但是原生控件使用起来也有局限性,这个时候呢Android也有给开发者提供一些方式来根据需求进行自定义,今天介绍自定义控件之手势解锁控件,效果如图
Android 自定义View之手势解锁控件_第1张图片
九宫格手势解锁控件是目前用得最广泛的控件,先介绍一下实现思路;九宫格是基于容器来的 所以我们可以在自定义的时候继承与ViewGroup来实现,然后再ViewGroup里面构建出连线时需要的点,最后再构建需要连接的线和保存选中的点和线的走向。
接下来看看实现:
步骤一:定义一个类继承与RelativeLayout
步骤二:定义出画笔和点的坐标、颜色、以及存储和答案
步骤三:测量控件的宽高和通过计算出的间距添加到布局中

private void setLockViewParams(LockViewFactory lockViewFactory) {if (mILockViews.size() > 0) {  return;}if (mLockViewMargin == 0) {  mLockViewMargin = (DisplayUtils.dp2px(getContext(), 250) - mLockViewWidth * mDotCount) / (mDotCount - 1);}for (int i = 0; i < mDotCount * mDotCount; i++) {  ILockView iLockView = lockViewFactory.newLockView();  iLockView.getView().setId(i + 1);  mILockViews.add(iLockView);  RelativeLayout.LayoutParams lockerParams = new LayoutParams(mLockViewWidth, mLockViewWidth);  //不是每行的第一个,则设置位置为前一个的右边  if (i % mDotCount != 0) {    lockerParams.addRule(RelativeLayout.RIGHT_OF, mILockViews.get(i - 1).getView().getId());  }  //从第二行开始,设置为上一行同一位置View的下面  if (i > mDotCount - 1) {    lockerParams.addRule(RelativeLayout.BELOW,        mILockViews.get(i - mDotCount).getView().getId());  }  //设置右下左上的边距  int rightMargin = 0;  int bottomMargin = 0;  int leftMargin = 0;  int topMargin = 0;  //每个View都有右外边距和底外边距 第一行的有上外边距 第一列的有左外边距  if (i >= mDotCount) {//非第一行    topMargin = mLockViewMargin;  }  if (i % mDotCount != 0) {//非第一列    leftMargin = mLockViewMargin;  }  lockerParams.setMargins(leftMargin, topMargin, rightMargin, bottomMargin);  mILockViews.get(i).onNoFinger();  mILockViews.get(i).getView().setLayoutParams(lockerParams);  addView(mILockViews.get(i).getView());}  }

步骤四:处理按下和移动 抬起事件

 @Overridepublic boolean onTouchEvent(MotionEvent event) {if (mTouchable) {  int action = event.getAction();  int x = (int) event.getX();  int y = (int) event.getY();  switch (action) {    case MotionEvent.ACTION_DOWN:      handleDownEvent(x, y);      break;    case MotionEvent.ACTION_MOVE:      handleMoveEvent(x, y);      break;    case MotionEvent.ACTION_UP:      handleUpEvent();      break;  }  invalidate();  return true;} else {  return false;} }

按下时需要复位View,处理移动事件

private void handleMoveEvent(int x, int y) {mPaint.setColor(mFingerTouchColor);ILockView lockView = getLockViewByPoint(x, y);if (lockView != null) {  int childId = lockView.getView().getId();  if (!mChooseList.contains(childId)) {    mChooseList.add(childId);    lockView.onFingerTouch();    //手势解锁监听    if (mOnLockVerifyListener != null) {      mOnLockVerifyListener.onGestureSelected(childId);    }    mLastPathX = lockView.getView().getLeft() / 2 + lockView.getView().getRight() / 2;    mLastPathY = lockView.getView().getTop() / 2 + lockView.getView().getBottom() / 2;    if (mChooseList.size() == 1) {      mPath.moveTo(mLastPathX, mLastPathY);    } else {      mPath.lineTo(mLastPathX, mLastPathY);    }  }}//指引线终点坐标mLineX = x;mLineY = y;}

处理抬起事件:

  private void handleUpEvent() {if (mCurrentMode == RESET_MODE) {  handleResetMode();} else {  handleVerifyMode();}//将指引线的终点坐标设置为最后一个Path的原点,即取消指引线mLineX = mLastPathX;mLineY = mLastPathY;}

步骤五:记录和保存

@Overrideprotected Parcelable onSaveInstanceState() {Parcelable superState = super.onSaveInstanceState();SavedState ss = new SavedState(superState);ss.tryTimes = mTryTimes;return ss;  }

步骤六:校验

  /** * 检查答案是否正确   */private boolean checkAnswer() {    if (mAnswerList.size() != mChooseList.size()) {      return false;    }    for (int i = 0; i < mAnswerList.size(); i++) {      if (mAnswerList.get(i) != mChooseList.get(i) - 1) {        return false;      }    }return true;  }  /**   * 切换LockView是否匹配状态   */  private void toggleLockViewMatchedState(boolean isMatched) {if (isMatched) {  mPaint.setColor(mFingerUpMatchedColor);} else {  mPaint.setColor(mFingerUpUnmatchedColor);}for (ILockView iLockView : mILockViews) {  if (mChooseList.contains(iLockView.getView().getId())) {    if (!isMatched) {      iLockView.onFingerUpUnmatched();    } else {      iLockView.onFingerUpMatched();    }  }} }

OK,结束 代码已经上传到 我的资源

更多相关文章

  1. Android重要控件概览(中)
  2. Android常用布局、控件以及Android存储方式
  3. android xml控件属性
  4. Android控件之EditText(输入文本框控件)
  5. Android--DatePickerDialog日期控件
  6. android > 控件 > RadioGroup
  7. Android Studio 基础控件使用
  8. android时间控件DigitalClock的使用
  9. android Switch控件

随机推荐

  1. Android(安卓)QuickSetting---手电筒控制
  2. getContentResolver().query 和 managedQ
  3. ListView与BaseAdapter优化
  4. Android:inflate.inflate()方法
  5. Android(安卓)UI编程(1)——九宫格(GridV
  6. Android(安卓)利用程序实现GPS的打开或关
  7. 严苛模式(StrictMode)
  8. Android消息机制(Handler、Looper、Messa
  9. android基础总结篇之九:Intent应用详解
  10. Android模拟器SD卡的使用