关于九宫格解锁,我看了不少博客,但是都感觉很复杂,可能我的功夫还不到,所以很多东西我不了解,但是我还是打算写一个自己的九宫格。我相信我的九宫格大家都能很快的理解,当然如果需要实现更复杂的功能,需要大家自己接着往深了挖掘。

代码文件​​​​​​

NineGroupView:为九宫格空间组

ToggleView:九宫格中的子View,也就是我们看到的圆形按钮,我自己定义的ToggleView可能不好看,当然大家可以自己定义更加好看的ToggleView。

MarkBean:记录ToggleView的索引(ChildIndex)以及是否选中的状态

PositionUtils:工具类,包含规划九个ToggleView的中心点位置,判断当前触摸点是否属于ToggleView中等方法。

NineActivity:测试页面。

布局规划图
public class PositionUtils {/*** 判断触摸的点是否属于View中的一点** @param point    触摸的点* @param position 目标对象圆形坐标* @param outR     目标对象的外半径* @return*/public static boolean IsIn(Point point, Point position, int outR) {int touchX = point.x;int touchY = point.y;int cx = position.x;int cy = position.y;int distance = (int) Math.sqrt(Math.pow((touchX - cx), 2) + Math.pow((touchY - cy), 2));if (distance <= outR) {return true;} else {return false;}}/*** 规划 child 的中心位置** @param width* @param height* @return*/public static List<Point> getNinePoints(int width, int height) {List<Point> points = new ArrayList<>();for (int i = 1; i <= 3; i++) {for (int j = 1; j <= 3; j++) {points.add(getPoint(width, height, 0.25f * j, 0.2f * i + 0.1f));}}return points;}/*** 获取** @param width  父控件的宽* @param height 父控件的高* @param x      横轴方向比例* @param y      纵轴方向的比例* @return*/private static Point getPoint(int width, int height, float x, float y) {Point point = new Point();point.x = (int) (width * x);point.y = (int) (height * y);return point;}}
public class ToggleView extends View {private Paint inPaint;private Paint outPaint;private int outColor;private int inColor;private int outR;private int inR;private boolean isChecked;public int getOutColor() {return outColor;}public void setOutColor(int outColor) {this.outColor = outColor;}public int getInColor() {return inColor;}public void setInColor(int inColor) {this.inColor = inColor;}public int getOutR() {return outR;}public void setOutR(int outR) {this.outR = outR;}public int getInR() {return inR;}public void setInR(int inR) {this.inR = inR;}public boolean isChecked() {return isChecked;}public void setChecked(boolean checked) {isChecked = checked;}public ToggleView(Context context) {this(context, null);}public ToggleView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public ToggleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs, defStyleAttr);}/*** 初始化*/private void init(Context context, AttributeSet attrs, int defStyleAttr) {TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ToggleView, defStyleAttr, 0);int indexCount = array.getIndexCount();for (int i = 0; i < indexCount; i++) {int attr = array.getIndex(i);switch (attr) {case R.styleable.ToggleView_InCircleR_T:inR = array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(Dimension.DP, 10, getResources().getDisplayMetrics()));break;case R.styleable.ToggleView_OutCircleR_T:outR = array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(Dimension.DP, 50, getResources().getDisplayMetrics()));break;case R.styleable.ToggleView_InCircleColor_T:inColor = array.getColor(attr, 0xff00ffff);break;case R.styleable.ToggleView_OutCircleColor_T:outColor = array.getColor(attr, 0xff888888);break;}}inPaint = new Paint();inPaint.setStyle(Paint.Style.FILL_AND_STROKE);inPaint.setColor(inColor);inPaint.setAntiAlias(true);outPaint = new Paint();outPaint.setAntiAlias(true);outPaint.setStrokeWidth(5);outPaint.setStyle(Paint.Style.STROKE);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int cx = getWidth() / 2;int cy = getHeight() / 2;outPaint.setStyle(Paint.Style.FILL);outPaint.setColor(Color.WHITE);canvas.drawCircle(cx, cy, outR, outPaint);outPaint.setStyle(Paint.Style.STROKE);outPaint.setColor(outColor);canvas.drawCircle(cx, cy, outR, outPaint);canvas.drawCircle(cx, cy, inR, inPaint);}
}
public class NineGroupView extends ViewGroup {private OnFinishListener mListener;public interface OnFinishListener {public void onFinish(List<Integer> positionSet);}public void setOnFinishListener(OnFinishListener listener) {this.mListener = listener;}private Paint paint;private Path path;private TreeMap<Integer, Boolean> checkedMap;private List<Integer> checkedINdexSet;   //用于记录被选中的序号排列。private List<Point> positionList;private List<Point> childSize = new ArrayList<>();public NineGroupView(Context context) {this(context, null);}public NineGroupView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public NineGroupView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public void reset() {for (int i = 0; i < 9; i++) {checkedMap.put(i, false);}checkedINdexSet.clear();IsDownIn = false;IsUp = false;path.reset();prePoint = new Point(-1, -1);currentPoint = new Point(-1, -1);invalidate();}private void init() {checkedMap = new TreeMap<>();for (int i = 0; i < 9; i++) {checkedMap.put(i, false);}checkedINdexSet = new ArrayList<>();positionList = new ArrayList<>();path = new Path();paint = new Paint();paint.setStrokeWidth(10);paint.setAntiAlias(true);paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);//如果该方法在此不调用的话,那么onDraw()方法将不被调用,那么就无法完成连接线的绘制setWillNotDraw(false);}@Overrideprotected void onLayout(boolean b, int left, int top, int right, int bottom) {int height = getMeasuredHeight();int width = getMeasuredWidth();positionList = PositionUtils.getNinePoints(width, height);int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View child = getChildAt(i);Point size = childSize.get(i);Point position = positionList.get(i);int cLeft = position.x - size.x;int cTop = position.y - size.y;int cRight = position.x + size.x;int cBottom = position.y + size.y;child.layout(cLeft, cTop, cRight, cBottom);}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View child = getChildAt(i);measureChild(child, widthMeasureSpec, heightMeasureSpec);Point point = new Point();point.x = child.getMeasuredWidth();point.y = child.getMeasuredHeight();childSize.add(point);}setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);}private boolean IsDownIn = false;private boolean IsUp = false;private Point prePoint = new Point(-1, -1);private Point currentPoint = new Point(-1, -1);@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();int currentX = (int) event.getX();int currentY = (int) event.getY();switch (action) {case MotionEvent.ACTION_DOWN: {if (IsUp) {return true;}MarkBean bean = isInToggle(new Point(currentX, currentY));if (bean != null) {IsDownIn = true;prePoint = positionList.get(bean.getIndex());path.moveTo(prePoint.x, prePoint.y);invalidate();}}break;case MotionEvent.ACTION_UP:IsUp = true;if (IsDownIn) {currentPoint = prePoint;IsDownIn = false;invalidate();if (mListener != null) {mListener.onFinish(checkedINdexSet);reset();}}break;case MotionEvent.ACTION_MOVE: {if (IsDownIn) {if (!IsUp) {MarkBean bean = isInToggle(new Point(currentX, currentY));if (bean != null) {int index = bean.getIndex();currentPoint = positionList.get(index);path.lineTo(currentPoint.x, currentPoint.y);invalidate();prePoint = currentPoint;} else {currentPoint = new Point(currentX, currentY);invalidate();}}} else {if (!IsUp) {MarkBean bean = isInToggle(new Point(currentX, currentY));if (bean != null) {Point position = positionList.get(bean.getIndex());prePoint = position;path.moveTo(position.x, position.y);IsDownIn = true;invalidate();}}}}break;case MotionEvent.ACTION_CANCEL:break;}return true;}private MarkBean isInToggle(Point point) {MarkBean bean = new MarkBean();int childCount = getChildCount();for (int i = 0; i < childCount; i++) {Point position = positionList.get(i);ToggleView child = (ToggleView) getChildAt(i);if (PositionUtils.IsIn(point, position, child.getOutR())) {if (!checkedMap.get(i)) {checkedMap.put(i, true);checkedINdexSet.add(i);bean.setIndex(i);bean.setCheck(true);return bean;}}}return null;}@Overrideprotected void onDraw(Canvas canvas) {canvas.drawPath(path, paint);if (prePoint.x != -1 && prePoint.y != -1 && currentPoint.x != -1 && currentPoint.y != -1) {canvas.drawLine(prePoint.x, prePoint.y, currentPoint.x, currentPoint.y, paint);}super.onDraw(canvas);}
}

代码总是最直接的引导,我看博客最喜欢的是研究代码,当然如果代码中有一些讲解就更好了。

自定义控件--最简单九宫格解锁相关推荐

  1. 高仿支付宝钱包九宫格解锁

    转载请表明出处:http://blog.csdn.net/forsxj/article/details/45221933 废话不多说,上效果图,先是高仿: 下面是正版的: 大体上实现了支付宝钱包九宫格 ...

  2. 九宫格解锁的完全实现

    前言 不记得在使用诺基亚的那些日子,为了一个九宫格解锁,在应用商城里下了多少流氓软件.最后无功而返的时候,那种郁闷的心情恨不得把手机给砸了!不得不承认,九宫格解锁的一时风靡,以致于Android阵营的 ...

  3. Android之九宫格解锁的实现

    九宫格解锁在Android中应用的很广泛,也是Android特有的一种解锁方式,其实实现起来也并不是很复杂,下面我就根据系统源码LockPatternView,移植出来的一个更加简单小巧九宫格解锁的例 ...

  4. 9宫格解锁 android_Android实现九宫格解锁的实例代码

    当年感觉九宫格解锁很是高大上,一脸懵逼,今天正好要做解锁这一块业务,回头来看九宫格,这特么简单啊 首先理清一下逻辑,我们要做NxN的九宫格 下图是3x3的简单图例 // -(--)-(--)-(--) ...

  5. android 九宫格解锁源码,Android 自己动手实现滑动九宫格解锁

    Android 自己动手实现滑动九宫格解锁 文章主要以实现思路为主.来带领大家逐步实现该效果功能.如有问题,请多多提出 效果预览 整体思路分析 九宫格滑动解锁,为当下比较热门的手机,Pad等触屏设备很 ...

  6. android九宫格布局解锁,Android onDraw()--九宫格解锁

    onDraw这个方法在自定义中尤其重要,我们可以measure之后通过Canvas进行绘制,九宫格解锁这个View现在已经被人脸跟指纹给替代了,但是做起来还是有点东西的. 下面就是做这个View的思路 ...

  7. Android九宫格解锁

    当年感觉九宫格解锁很是高大上,一脸懵逼,今天正好要做解锁这一块业务,回头来看九宫格,这特么简单啊 首先理清一下逻辑,我们要做NxN的九宫格 下图是3x3的简单图例 // -(–)-(–)-(–)- / ...

  8. Touch事件分发 九宫格解锁

    ###1.概述 自定义View效果越写越难,但是将这些效果一步一步分解后,其实挺简单的,早期自己项目中用到九宫格解锁,我都是从网上下的,因为心里一开始觉得自己写应该会很困难,后来发现自己闲下来写写原来 ...

  9. 9宫格解锁 android_Android实现九宫格解锁

    相信大家都有使用九宫格解锁,比如在设置手机安全项目中,可以使用九宫格解锁,提高安全性,以及在使用支付功能的时候,为了提高安全使用九宫锁,今天就为大家介绍Android实现九宫格的方法,分享给大家供大家 ...

最新文章

  1. MySQL两主多从,且故障转移配置
  2. 七年级上册数学计算机教学视频,七年级上册数学教学视频免费
  3. Spring Boot干货系列:(二)配置文件解析
  4. 三星全速进军物联网 所有产品都将内置互联功能
  5. 帖子回复——无限级分类
  6. 上探式提额与倒逼式提额—风控调额就该这么做
  7. python 中 enumerate() 函数使用
  8. 基于中颖SH79F168单片机的航模无刷电调方案
  9. 计算机设备硬件维护税收编码,自动化设备的税收编码是多少
  10. php 微信表情字符,微信公众平台开发--表情符号
  11. vue引入百度离线地图
  12. 2、Docker部署的Onlyoffice中文字体修改
  13. 软件工程阶段性总结(四)——测试和维护
  14. Ceph RBD 使用详细说明
  15. gggggggggggggggggdsfdsf
  16. 网络攻防--网络防御技术(一)
  17. 《2022-移动端游戏版号申请详解》
  18. html中的 语言设置
  19. 域名怎么卖:建站出售
  20. 简历包装被公司查出来了。。。

热门文章

  1. python绘制繁花曲线代码_使用python和pygame绘制繁花曲线
  2. 华为云ECS服务器中通过docker部署ELK-elasticsearch
  3. 应该清理CBA场内和场外的垃圾
  4. 用C语言写一个可以选择关卡添加关卡的小游戏,推箱子
  5. 公司员工考勤问题应当如何解决?
  6. js 和jQuery(自动执行函数)立即执行函数和页面加载完后执行函数写法
  7. 国土空间规划属性刷插件
  8. 碳化硅衬底和MEMS晶圆的研磨抛光技术
  9. QT中main函数中加载外部字体:OTF
  10. 代码随想录打卡第九天