900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 自定义控件--最简单九宫格解锁

自定义控件--最简单九宫格解锁

时间:2024-03-10 05:50:24

相关推荐

自定义控件--最简单九宫格解锁

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

代码文件​​​​​​

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);}}

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。