九宫格程序设计

本文介绍九宫格程序的设计代码。

一.相关介绍

(一)效果显示

1.程序刚运行时的效果:

j1

2.在页面上点击选择并滑动时的画面

j2

3.选择密码之后的显示

j3

(二)功能介绍

1.点击某圆圈后,在该圆圈的中心添加一个实行的小圆
2.页面滑动出现一条跟随的线
3.滑动到另一个圆圈时,产生一条连接的直线
4.选择的圆圈点数大于等于4个后,手指抬起,就会保存密码。
4.选择的圆圈的数是最大值后,马上保存密码。

(三)涉及到的知识点

  • 本示例使用的是自定义的View来绘制九宫格,并保存图像
  • 这里的九个点分别代表的是九个数值,获取到对应的数值证明绘制了那个点
  • 程序中使用到的知识:
  • 1、图像的描绘,圆和点的描绘,线的描绘
  • 2、位置的判断,判断用户点的位置是否在某一个圆内
  • 3、保存数据和相关判断

二.程序设计

(一)自定义View的设计

 package com.lwz.gongge;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/10/28 0028.
 */

public class NineGridView extends View {
    //构造方法
    public NineGridView(Context context) {
        super(context);
        init();
    }

    //构造方法
    public NineGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    //定义一个画实心圆的画笔
    Paint paintCircle;
    //定义一个画线的画笔
    Paint paintLine;
    //定义一个宽度值,大概是屏幕的四分之一,代表的是每一个圆点间的x轴距离
    int width;
    //定义一个背景颜色
    int backColor;
    //定义一个集合用来存放点击过的圆点0到8表示九个点
    List<Integer> listPassword = new ArrayList<>();
    //触屏的位置
    float currX, currY;
    //密码的个数
    int minPassNum = 4;
    int maxPassNum = 9;

    //初始化
    private void init() {
        //定义背景颜色
        backColor = Color.rgb(0x17, 0x16, 0x25);
        //实例化画笔,并作基本设置
        paintLine = new Paint();
        paintLine.setAntiAlias(true);
        paintLine.setDither(true);
        paintLine.setColor(Color.rgb(0x37, 0x91, 0xe6));

        paintCircle = new Paint();
        paintCircle.setAntiAlias(true);
        paintCircle.setDither(true);
        paintCircle.setColor(backColor);

    }

    //丈量屏幕时回调的方法,在这个方法内可以取得屏幕的宽度
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getWidth() / 4;
    }


    //屏幕图像绘制回调的方法
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置屏幕的颜色,(清屏)
        canvas.drawColor(backColor);

        //画线,如果数据集合内有数据才能去画线
        if (listPassword.size() > 0) {
            //求出最后画的那个点来做画线
            //这里求得是坐标点
            int x = listPassword.get(listPassword.size() - 1) % 3 + 1;//x轴的方向
            int y = listPassword.get(listPassword.size() - 1) / 3 + 1;//y轴的方向
            //设置画线的大小
            paintLine.setStrokeWidth(8);
            //画线,从具体点的位置到触屏的位置
            canvas.drawLine(x * width, y * width, currX, currY, paintLine);
            //再画一个圆覆盖掉圆圈内的那些线
            canvas.drawCircle(x * width, y * width, width / 3, paintCircle);

            //如果集合的数据中还有其他的点的数据
            if (listPassword.size() > 1) {
                //按顺序画线
                for (int i = 0; i < listPassword.size() - 1; i++) {//防止越界
                    //获取当前的一个i和后面的一个i
                    //前一个点的坐标点
                    int x1 = listPassword.get(i) % 3 + 1;
                    int y1 = listPassword.get(i) / 3 + 1;
                    //后一个点的坐标点
                    int x2 = listPassword.get(i + 1) % 3 + 1;
                    int y2 = listPassword.get(i + 1) / 3 + 1;
                    //设置画笔的大小
                    paintLine.setStrokeWidth(8);
                    //画线,从上一个点的位置到下一个点的位置
                    canvas.drawLine(x1 * width, y1 * width, x2 * width, y2 * width, paintLine);
                    //再画一个圆覆盖掉圆圈内的那些线,这里覆盖的是后面的一个圆的线
                    canvas.drawCircle(x1 * width, y1 * width, width / 3, paintCircle);
                }
            }

        }


        //绘制九个圆圈,用的是线
        //设置宽度
        paintLine.setStrokeWidth(2);
        //设置空心必须要的
        paintLine.setStyle(Paint.Style.STROKE);
        //开始画圆9个,这里圆的半径暂时设置为圆距离的3分之一
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                //一个参数是圆点的x轴的坐标值
                //二个参数是圆点的y轴的坐标值
                canvas.drawCircle(width * (i + 1), width * (j + 1), width / 3, paintLine);
                //这里的图像的y轴上不一定是在中心,但是整体是个正方形,效果差不多就可以了
            }
        }

        //绘制实心圆在圆圈里面,颜色和外面的圆圈的颜色是一样的,用同一只笔
        //这里要判断你划过几个点,对集合进行遍历
        //设置实心样式
        paintLine.setStyle(Paint.Style.FILL);
        for (int i = 0; i < listPassword.size(); i++) {
            //取出集合里面的数
            int p = listPassword.get(i);
            int x = p % 3;
            int y = p / 3;
            //一个参数是圆点的x轴的坐标值
            //二个参数是圆点的y轴的坐标值
            canvas.drawCircle(width * (x + 1), width * (y + 1), width / 6, paintLine);
        }


    }

    //触摸屏幕的监听事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //获取用户点击的坐标位置
        float x = event.getX();
        float y = event.getY();

        //判断用户的行为并作相应的操作
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://触屏时
                //判断用户是否点击在某个圆点范围内
                if (connetCircle(x, y) != -1) {
                    //更新位置
                    currX = x;
                    currY = y;
                    //把这个点的位置添加到存放数据的集合中
                    listPassword.add(connetCircle(x, y));
                }

                break;
            case MotionEvent.ACTION_UP://手指抬起时
                //如果密码的值到到达最小位数后保存密码给主页面
                if (listPassword.size() >= minPassNum) {
                    //如果另一边实现了监听事件,那么就给他数据
                    if (listener != null) {
                        //把密码传递过去
                        listener.toListenerThePassword(getPasswordString());
                    }
                }
                //清空数据
                listPassword.clear();
                break;
            case MotionEvent.ACTION_MOVE://手指移动时
                //更新位置
                currX = x;
                currY = y;
                //移动到其他的圆中,那么就添加数据到集合中
                //获取该点的位置
                int point = connetCircle(x, y);
                //如果这个点是在圆内,并且数据里面不包含这个点的值,那么就添加这个点的值到集合中
                if (point != -1 && !listPassword.contains((Integer) point)) {
                    listPassword.add(point);
                }
                //如果密码的值到到最大值后保存密码给主页面
                if (listPassword.size() >= maxPassNum) {
                    //如果另一边实现了监听事件,那么就给他数据
                    if (listener != null) {
                        //把密码传递过去
                        listener.toListenerThePassword(getPasswordString());
                    }
                    break;
                }
        }
        //不管是上面是什么行为最后都要刷新一下屏幕
        invalidate();//屏幕重绘
        return true;
    }

    //判断用户点击的地方是否在某一个圆点内
    private boolean isInCircle(float x, float y, float cx, float cy) {
        //x、y代表的是坐标位置
        //cx、cy代表的是圆坐标位置
        //圆点半径是width/3
        //如果点击的位置减去圆心的位置的平方小于半径的平方那么这个点是在圆内的
        return (x - cx) * (x - cx) + (y - cy) * (y - cy) < (width / 3) * (width / 3);
    }

    //判断用户点击的地方是否在九个圆点的哪一个圆点内
    private int connetCircle(float x, float y) {
        //x、y代表的是坐标位置
        //依次判断每个圆圈看看是否在它的里面
        //圆点的坐标位置-->(width,width)--(2*width,width)--(3*width,width)
        //--->(width,2*width)--(2*width,2*width)--(3*width,2*width)
        //--->(width,3*width)--(2*width,3*width)--(3*width,3*width)
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (isInCircle(x, y, width * (j + 1), width * (i + 1))) {//(i,j)
                    //如果点击是圆,就把这个点的值添加到集合中
                    //0  1  2      (0,0)/(0,1)/(0/2)
                    //3  4  5      (1,0)/(1,1)/(1/2)
                    //6  7  8      (2,0)/(2,1)/(2/2)
                    //如果是7,那么游标值(2,1)
                    //返回该点的值
                    return (3 * i + j);
                }

            }
        }
        //如果不在九个圆点位置就返回-1
        return -1;
    }

    //创建一个回调接口,让主页面监听这个事件
    interface onFinishListener {
        void toListenerThePassword(String s);
    }

    //设置一个监听接口的对象
    onFinishListener listener;

    //设置监听接口的方法
    public void setListener(onFinishListener listener) {
        this.listener = listener;
    }

    //获取密码的字符串
    public String getPasswordString() {
        //定义密码的字符串
        String pass = "";
        //取出集合里面的密码的数字
        for (int i = 0; i < listPassword.size(); i++) {
            pass += listPassword.get(i);
        }
        return pass;
    }

}

(二)主方法调用这个View的类

package com.lwz.gongge;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;


public class MainActivity extends AppCompatActivity {

    //自定义View传递过来的密码
    String password = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //定义自定义的View并实例化
        NineGridView nine = new NineGridView(this);
        //显示自定义的View
        setContentView(nine);

        //通过监听方法来获取自定义传来的密码

        //给视图设置监听事件
        nine.setListener(new NineGridView.onFinishListener() {
            @Override
            public void toListenerThePassword(String pass) {
                //这里的pass是自定义View里面,传过来的数据
                password = pass;
                //土司密码
                Toast.makeText(MainActivity.this, "密码:" + password, Toast.LENGTH_SHORT).show();
            }
        });


    }
}

     上面就是九宫格程序设计的代码了。这里没有用到xml的布局文件,都是用代码实现的。

     完成自定义View后,调用和使用都是比较简单的,可以作为一个工具类使用,获取到自定义View传过来的密码,可以做其他保存操作,比如保存到本地文件或数据库中,这里只是做了土司操作,让用户看到效果。

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值