关于九宫格解锁,我看了不少博客,但是都感觉很复杂,可能我的功夫还不到,所以很多东西我不了解,但是我还是打算写一个自己的九宫格。我相信我的九宫格大家都能很快的理解,当然如果需要实现更复杂的功能,需要大家自己接着往深了挖掘。
代码文件
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); } @override protected 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); } @override protected 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); } } @override protected 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); @override public 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; } @override protected 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); } }
代码总是最直接的引导,我看博客最喜欢的是研究代码,当然如果代码中有一些讲解就更好了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。