iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Android开发中中怎么实现投放九宫格手势密码功能
  • 235
分享到

Android开发中中怎么实现投放九宫格手势密码功能

androidroi 2023-05-31 09:05:37 235人浏览 八月长安
摘要

这篇文章将为大家详细讲解有关Android开发中中怎么实现投放九宫格手势密码功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。要实现九宫格密码要解决的问题有:给九宫格密码界面布局九个点,即确

这篇文章将为大家详细讲解有关Android开发中中怎么实现投放九宫格手势密码功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

要实现九宫格密码要解决的问题有:

给九宫格密码界面布局九个点,即确定每个节点的位置。每个点到上下左右的距离都是相同的。即九个点刚好围成一个正方形。所以这样的布局界面无法用现有的五大布局来完成必须自定义这个控件。

每个节点只能被选择一次,所以必须记录每个点的选中状态。

手势开始滑动时,每个节点如何知道手势运动的轨迹经过自己。

连线,连线如果步考虑效果,直接用canvas的drawline方法来画连线时当然是很简单的。但是如果用图线(即联系用用一个Bitmap)来画,如何画。解决了这四个问题我们就可以做九宫格密码了。

记录被选择节点的顺序。

带着这是那个问题我们开始实现我们要实现的效果。因为网上好多事例所以我就直接拿别人的事例来消化吧。为了更好的解读这个问题我先把代码贴出来后面在讲解这样我觉得我会刚好说一些,大家也更容易理解一些 

package org.demo.custon_view;  import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView;   public class SquaredPassWord extends View {  ImageView i;  private int length;// 九宫格密码是正方形所以只要知道边长就可以  private Point[] points = new Point[9];// 九宫格节点  private Bitmap defualtPointMap = BitmapFactory.decodeResource(getResources(), R.drawable.locus_round_original);// 正常情况下点的位图  private int poitleght = defualtPointMap.getWidth();// 节点的边长;这里值考虑正方形状态  private Bitmap selectPointMap = BitmapFactory.decodeResource(getResources(), R.drawable.locus_round_click);// 选中情况下点的位图  private Point startPoint;// 起点  private Point tempPoint;// 临时存储上一个节点  private StringBuffer passWBuffer = new StringBuffer();// 保存轨迹顺序的密码  private Bitmap lineBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.locus_line);  private int lineBitmapheight = lineBitmap.getHeight();  private double lineBitmapWidth = lineBitmap.getWidth();  // 以下四个变量是为了绘制最后一个跟手指之间的连线  private int startX;// 移动起点X  private int startY;// 移动起点Y  private int moveX;// 正在移动的X  private int moveY;// 正在移动的Y   public SquaredPassWord(Context context) {   super(context);   }   public SquaredPassWord(Context context, AttributeSet attrs) {   super(context, attrs);   }   public SquaredPassWord(Context context, AttributeSet attrs, int defStyle) {   super(context, attrs, defStyle);   }   @Override  public boolean onTouchEvent(MotionEvent event) {   boolean flag = true;   switch (event.getAction()) {   case MotionEvent.ACTION_DOWN:    passWBuffer.delete(0, passWBuffer.length());    int x = (int) event.getX();    int y = (int) event.getY();    for (Point point : points) {     if (point.isInMyArea(x, y)) {      point.setSelected(true);      tempPoint = startPoint = point;      startX = startPoint.getCenterX();      startY = startPoint.getCenterY();      passWBuffer.append(startPoint.getId());     }    }    invalidate();    break;   case MotionEvent.ACTION_MOVE:    moveX = (int) event.getX();    moveY = (int) event.getY();    for (Point point : points) {     if (point.isInMyArea(moveX, moveY) && !point.isSelected()) {      tempPoint.setNextID(point.getId());      point.setSelected(true);      tempPoint = point;      startX = tempPoint.getCenterX();      startY = tempPoint.getCenterY();      passWBuffer.append(tempPoint.getId());     }    }    invalidate();    break;   case MotionEvent.ACTION_UP:    reSetData();    startX = startY = moveX = moveY = 0;    invalidate();    flag = false;    break;    default:    break;   }   return flag;  }     private void reSetData() {   for (Point point : points) {    point.setSelected(false);    point.setNextID(point.getId());   }  }   @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   // TODO Auto-generated method stub   int width = getWidth() - getPaddingLeft() - getPaddingRight();   int height = getHeight() - getPaddingTop() - getPaddingBottom();   length = (width < height ? width : height);// 获取边长   if(!(length>0)){       }   System.out.println(length);   initPionts(points);   super.onMeasure(widthMeasureSpec, heightMeasureSpec);  }   @Override  protected void onDraw(Canvas canvas) {   // TODO Auto-generated method stub   if (moveX != 0 && moveY != 0 && startX != 0 && startY != 0) {    // 绘制当前活动的线段    drawLine(startX, startY, moveX, moveY, canvas);   }   drawLinePoint(canvas);   super.onDraw(canvas);  }     @SuppressWarnings("null")  private void initPionts(Point[] points) {   int spacing = (length - poitleght * 3) / 2;    if (points == null && points.length != 9) {// 只做九宫格的处理    return;   } else {    for (int i = 0; i < 9; i++) {     int row = i / 3;// 行数     int column = i % 3;// 列数;求整取余      int x = (poitleght + spacing) * column + getPaddingLeft();// x坐标     int y = (poitleght + spacing) * row + getPaddingTop();// y坐标     Point point = new Point((i + 1), x, y, poitleght);     points[i] = point;    }   }  }     private void drawLinePoint(Canvas canvas) {   if (startPoint != null) {    drawP2POrbit(startPoint, canvas);   }   Paint paint = null;// new Paint();   // 绘制每个点的图片   for (Point point : points) {    if (point.isSelected()) {// 绘制大圈     canvas.drawBitmap(selectPointMap, point.getX(), point.getY(), paint);    } else {     canvas.drawBitmap(defualtPointMap, point.getX(), point.getY(), paint);    }   }  }     private void drawP2POrbit(Point point, Canvas canvas) {   if (point.getId() != point.nextID) {    // canvas.concat(matrix);    Point endPoint = null;    // 获取目标节点    for (Point point3 : points) {     if (point3.getId() == point.getNextID()) {      endPoint = point3;      break;     }    }    if (endPoint != null) {     // 画线     drawLine(point.getCenterX(), point.getCenterY(), endPoint.getCenterX(), endPoint.getCenterY(), canvas);     // 递归     drawP2POrbit(endPoint, canvas);    }   }  }     private void drawLine(int startX, int startY, int stopX, int stopY, Canvas canvas) {   Paint paint = new Paint();   // 获得斜边长度   double hypotenuse = Math.hypot((stopX - startX), (stopY - startY));   // double side = stopX - startX;// 邻边   // double piAngle = Math.acos(side / hypotenuse);// pi角度   // float rotate = (float) (180 / Math.PI * piAngle);// 转换的角度   float rotate = getDegrees(startX, startY, stopX, stopY);   Matrix matrix = new Matrix();   // matrix.postRotate(rotate);//不能用这个matritx 来选择角度只能用 让canvas懒选择     // 用matrix的话会引起图片所表示的线条不在中心点上     canvas.rotate(rotate, startX, startY);   matrix.preTranslate(0, 0);   matrix.setScale((float) (hypotenuse / lineBitmapWidth), 1.0f);   matrix.postTranslate(startX, startY - lineBitmapheight / 2.f);   canvas.drawBitmap(lineBitmap, matrix, paint);   canvas.rotate(-rotate, startX, startY);//恢复   canvas.save();  //  Paint paint1 = new Paint(); //  paint1.setColor(Color.BLACK); //  paint1.setStrokeWidth(8);// 粗细 //  paint1.setFlags(Paint.ANTI_ALIAS_FLAG); //  canvas.drawLine(startX, startY, stopX, stopY, paint1);   }     private float getDegrees(int startX, int startY, int stopX, int stopY) {   // 获得斜边长度   double hypotenuse = Math.hypot((stopX - startX), (stopY - startY));   double side = stopX - startX;// 邻边   double piAngle = Math.acos(side / hypotenuse);// pi角度   float rotate = (float) (180 / Math.PI * piAngle);// 转换的角度(0--180);   if (stopY - startY < 0) {// 如果Y愁小于0说明角度在第三或者第四像限    rotate = 360 - rotate;   }   return rotate;  }     public String getOrbitString() {   return (passWBuffer == null ? null : passWBuffer.toString());  }     class Point {    private int id;// 点的id   private int nextID;// 连向下一个借点的id   private int x;// 点的左上角x坐标   private int y;// 点的左上角的y坐标   private boolean isSelected;// 该节点是否被选中   private int width;// 点的长度 这里只考虑正方形    public Point() {    super();    // TODO Auto-generated constructor stub   }    public int getId() {    return id;   }    public void setId(int id) {    this.id = id;   }    public int getNextID() {    return nextID;   }    public void setNextID(int nextID) {    this.nextID = nextID;   }    public int getX() {    return x;   }    public void setX(int x) {    this.x = x;   }    public int getY() {    return y;   }    public void setY(int y) {    this.y = y;   }    public boolean isSelected() {    return isSelected;   }    public void setSelected(boolean isSelected) {    this.isSelected = isSelected;   }    public int getWidth() {    return width;   }    public void setWidth(int width) {    this.width = width;   }    public Point(int id, int x, int y, int width) {    super();    this.id = id;    this.x = x;    this.y = y;    this.nextID = id;    this.isSelected = false;    this.width = width;   }    public int getCenterX() {    return x + (width / 2);   }    private int getCenterY() {    return y + (width / 2);   }       public boolean isInMyArea(int x, int y) {     // return (this.x < x && x < (this.x + width)) && (this.y < y && y <    // (this.y + width));    return ((this.getCenterX() - lineBitmapWidth / 2) < x && x < (this.getCenterX() + lineBitmapWidth / 2))      && ((this.getCenterY() - lineBitmapWidth / 2) < y && y < (this.getCenterY() + lineBitmapWidth / 2));   }  } }

1、布局九个节点。将九个节点布局起来首先要知道控件宽和高,这样我们才能如何布局,在onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法中用getWidth()和getHeight(); 方法我们就可以得到高度和宽度,因为自定义布局还有一个padding属性,所以我们还要计算这个步骤。所以计算真正布局这九个节点的正方形的边长(我们这里是做正方形的九宫格)为:
int width = getWidth() - getPaddingLeft() - getPaddingRight();
int height = getHeight() - getPaddingTop() - getPaddingBottom();
length = (width < height ? width : height);// 获取边长如果这个边长大于0我就开始确定九个节点分别的坐标位置。边长=三个节点的变长+两个间隙长度。

那么现在我们可以确定每个节点的位置了第一个节点为(0,0),第二节点为(0+pointwidth+spacing,0), ……。但是我们现在要做的首先是是怎样结论每个节点的位置,即定义一个节点的类。根据前面列出的几个问题可得出该节点要记录节点的id,起止坐标,被选中状态,节点的中心点坐标以及节点所连接的下一个节点的左边。根据这些性质我们写出了Point 的内部类如上面代码286行开始的定义。定义完了节点的类我们就开始为他们初始化如144还看是的initPionts方法。

2、画点以及画连线drawLinePoint方法所示用一个循环就可以把所有点画出来。绘制连线,现在有个情况要分析一下,1)点与点之间的连线即节点已经确定了加一个节点的id。2)节点与手势之间的连线,即节点还没有确定下一个节点前节点到手指的连线。先抛开画线这个方法不说画线就是画起点到终点的连线,这样我们可以先定义一个空发方法,传递canvas,以及表示两点坐标的参数传递给drawLine这个方法(220行开始),后面再去处理画线。根据先易后难的原则我们可以很容易的绘制点与点之间的连线如187行drawP2POrbit方法。麻烦就在点到手指的连线。干根据常识我们知道这个点肯定是最后被选中的那个点。而且这个点不是一成不变的所以我们得定义一个临时变量tempPoint来保存这个节点(不能用startPoit记录startPoint用保存最起点的位置)。而连线的终点就是手指的坐标点。这样就可以缺点两个节点下来了。见代码57行开始的onTouchEvent方法,该方法里头同时还记录的节点呗选中的顺序。这样我们就可以在ondraw方法画出了点和连线如128行开始。

3、画连线,drawLine(220行)这里我没什么要特别说的唯一要提起的就是反三角函数问题以及角度转化问题,反三角函数我不说了大家都会只是太长时间没用了忘了现在再去看一眼就行。而这个角度转化这块要特别注意一下我们要转化的是canvas的角度而不是bitmap的角度以为转化bitmap的角度的画很不容易确定bitmap的起点坐标因为bitmap以左上角作为起点坐标,随着角度的变化起点坐标也跟着变很难去计算。所以转换canvas的角度比较简单,最后在画晚线后别忘了再把角度转回来。并保存。

4、返回密码串getOrbitString(276行)是返回密码串的方法,在调用者(activity)的ontouch的Action_UP中调用就可以了。

关于Android开发中中怎么实现投放九宫格手势密码功能就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: Android开发中中怎么实现投放九宫格手势密码功能

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

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

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

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

下载Word文档
猜你喜欢
  • Android开发中中怎么实现投放九宫格手势密码功能
    这篇文章将为大家详细讲解有关Android开发中中怎么实现投放九宫格手势密码功能,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。要实现九宫格密码要解决的问题有:给九宫格密码界面布局九个点,即确...
    99+
    2023-05-31
    android roi
  • Android开发中怎么实现一个手势密码功能
    本篇文章为大家展示了Android开发中怎么实现一个手势密码功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。如果使用GestureOverlayView,在xml配置文件中使用Android.ge...
    99+
    2023-05-31
    android roi
  • 怎么在Android 应用中实现一个九宫格手势锁
    怎么在Android 应用中实现一个九宫格手势锁?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。主要的方法是重写View.onTouchEvent( Motion...
    99+
    2023-05-31
    android roi
  • Android开发中怎么实现一个音乐播放器功能
    Android开发中怎么实现一个音乐播放器功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。具体实现首先是布局文件中添加了如下代码,这些代码就是实现控制台的,给整体设置了一...
    99+
    2023-05-31
    android roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作