iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android自定义控件实现九宫格解锁
  • 370
分享到

Android自定义控件实现九宫格解锁

2024-04-02 19:04:59 370人浏览 薄情痞子
摘要

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

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

代码文件​​​​​​

NineGroupView:为九宫格空间组

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

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

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

NineActivity:测试页面。

布局规划图

public class PositionUtils {
    
    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;
        }
    }
 
    
    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;
    }
 
    
    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);
    }
}

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Android自定义控件实现九宫格解锁

本文链接: https://www.lsjlt.com/news/152864.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android自定义控件实现九宫格解锁
    关于九宫格解锁,我看了不少博客,但是都感觉很复杂,可能我的功夫还不到,所以很多东西我不了解,但是我还是打算写一个自己的九宫格。我相信我的九宫格大家都能很快的理解,当然如果需要实现更复...
    99+
    2024-04-02
  • Android自定义控件实现九宫格解锁功能
    最终Android九宫格解锁效果如下进行定义实体point点public class Point { private float x; private float y; //正常模式 public static final int NORM...
    99+
    2023-05-31
    android 九宫格 解锁
  • Android自定义view实现滑动解锁九宫格控件
    目录前言需求效果图前言 上一篇文章用贝塞尔曲线画了一个看起来不错的小红点功能,技术上没什么难度,主要就是数学上的计算。这篇文章也差不多,模仿了一个常用的滑动解锁的九宫格控件。 需求 ...
    99+
    2023-02-09
    Android滑动解锁九宫格 Android滑动解锁 Android九宫格控件
  • Android自制九宫格解锁控件
    本文实例为大家分享了Android自制九宫格解锁控件的具体代码,供大家参考,具体内容如下 前两天从网上学习了下如何自定义一个九宫格解锁的控件,于是自己根据逻辑写了一遍,自定义控件的代...
    99+
    2024-04-02
  • Android自定义ViewGroup实现朋友圈九宫格控件
    目录一、简介 1.1、效果图如下1.2、主要功能如下二、使用 2.1、自定义属性如下2.2、布局中使用自定义NineImageLayout2.3、Adapter方式绑定数据和UI2....
    99+
    2024-04-02
  • Android自定义View实现九宫格图形解锁(Kotlin版)
    本文实例为大家分享了Android自定义View实现九宫格图形解锁的具体代码,供大家参考,具体内容如下 效果: 代码: package com.example.kotlin_t...
    99+
    2024-04-02
  • Android如何自定义ViewGroup实现朋友圈九宫格控件
    本篇内容介绍了“Android如何自定义ViewGroup实现朋友圈九宫格控件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录一、简介1、...
    99+
    2023-06-20
  • Android怎么绘制九宫格解锁控件
    这篇“Android怎么绘制九宫格解锁控件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Android怎么绘制九宫格解锁控件...
    99+
    2023-06-29
  • android九宫格锁屏控件使用详解
    本文实例为大家分享了android九宫格锁屏控件的具体代码,供大家参考,具体内容如下 代码: public class LockView extends View {     //...
    99+
    2024-04-02
  • Android自定义九宫格输入框
    本文实例为大家分享了Android自定义九宫格输入框的具体代码,供大家参考,具体内容如下 效果 实现 绘制宫格分割线 这里我们用一个RectF类型的数组来装载数据。在onSizeC...
    99+
    2024-04-02
  • Android怎么实现九宫格解锁
    这篇文章主要介绍Android怎么实现九宫格解锁,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!首先理清一下逻辑,我们要做NxN的九宫格 下图是3x3的简单图例// -(--)-(--)-(--)-// -(--)-(...
    99+
    2023-05-30
    android
  • Android实现九宫格图案解锁
    本文实例为大家分享了Android实现九宫格图案解锁的具体代码,供大家参考,具体内容如下 前言:自定义了一个九宫格的VIew来绘制九宫格图案,实现了绘制图案解锁的功能。 效果图如下:...
    99+
    2024-04-02
  • Android怎么实现九宫格图案解锁
    今天小编给大家分享一下Android怎么实现九宫格图案解锁的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。效果图如下: 第一步...
    99+
    2023-07-02
  • Appium自动化测试实现九宫格解锁
    目录背景高级手势轻敲(tap)短按 (press)长按 (long_press)等待 (wait)移动到 (moveTo)释放 (release)执行 (perform)九宫格解锁背...
    99+
    2024-04-02
  • Android实现九宫格抽奖
    本文实例为大家分享了Android实现九宫格抽奖的具体代码,供大家参考,具体内容如下 package cq.cake.luckdraw; import android.graph...
    99+
    2024-04-02
  • Android实现图片九宫格
    本文实例为大家分享了Android实现图片九宫格的具体代码,供大家参考,具体内容如下 九宫格分三类 实现的效果 具体实现 activity_main <xml v...
    99+
    2024-04-02
  • Android RecyclerView实现九宫格效果
    RecyclerView更加优化的复用机制和方便实现UI效果,几乎替代Listview和GridView的使用。但是分割线的实现,需要自己继承ItemDecoration来绘制。 效...
    99+
    2024-04-02
  • Android实现九宫格手势密码
    本文实例为大家分享了Android实现九宫格手势密码的具体代码,供大家参考,具体内容如下 介绍下自己编写的九宫格手势密码。先见图 思路:首先是9个格子,接着是格子连线;那么我们的步...
    99+
    2024-04-02
  • Android 实现九宫格抽奖功能
    目录效果展示实现步骤 1.生成抽奖矩形:2.添加奖品图片:3.实现抽奖动画:4.实现动态设置参数:5.添加抽奖结果回调效果展示 实现步骤 1.生成抽奖矩形: 其中每个矩形的宽高相...
    99+
    2024-04-02
  • Android表格自定义控件使用详解
    近期公司要做报表功能,在网上搜索下表格的样式后便自己写了一个自定义的表格控件,该表格控件能根据设置的数据中数据的最大值自动设置左侧信息栏显示的值,使得条形图能尽量的充满控件,条形图部...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作