欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 自定义九宫格手势锁

程序员文章站 2023-11-17 22:28:22
 预览效果图如下: 主要的方法是重写view.ontouchevent( motionevent event ) , 常用的三个操作:action_down...

 预览效果图如下:

Android 自定义九宫格手势锁

主要的方法是重写view.ontouchevent( motionevent event ) , 常用的三个操作:action_down 手指触摸屏幕 ; action_up 手指离开屏幕;

action_move手指在屏幕滑动。

如果该方法返回true ,表示该事件已经被view处理,不再向上层的view或activity传递 ; 如果返回false, 表示事件未处理,继续传递。

具体代码如下:

package com.ninegrid;
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;
/**
 * created by administrator on 2017/6/24.
 */
public class suduview extends view {
  //定义默认常量
  private static final int default_cell_width = 200 ;
  private static final int default_cell_stroke_width = 10 ;
  private static final int default_space = 100 ;
  //九宫格数组
  private cell mcells[] = new cell[9] ;
  //直径
  private int mcellwidth;
  //半径
  private int mcellradius;
  //边框宽度
  private int mcellstrokewidth;
  //空白部分
  private int mspace ;
  //定义画笔
  private paint mpaintnormal ;
  private paint mpaintselected ;
  private float mcurrentx ;
  private float mcurrenty ;
  //判断是否结束的标识
  private boolean mfinish = false ;
  private stringbuffer msbselected = new stringbuffer(20);
  public suduview(context context) {
    super(context);
    init();
  }
  public suduview(context context, attributeset attrs) {
    super(context, attrs);
    init();
  }
  public suduview(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
    init();
  }
  private void init(){
    //初始化画笔
    mcellwidth = default_cell_width ;
    mcellradius = default_cell_width >> 1 ;
    mcellstrokewidth = default_cell_stroke_width ;
    mspace = default_space ;
    mpaintnormal = new paint();
    mpaintnormal.setcolor(color.white);
    mpaintnormal.setstrokewidth(mcellstrokewidth);
    mpaintnormal.setstyle(paint.style.stroke);
    mpaintnormal.setantialias(true);
    mpaintselected = new paint();
    mpaintselected.setcolor(color.cyan);
    mpaintselected.setstrokewidth(mcellstrokewidth);
    mpaintselected.setstyle(paint.style.stroke);
    mpaintselected.setantialias(true);
    cell cell ;
    float x;
    float y;
    //计算每个格子的坐标
    for( int i = 0 ; i < 9 ; i ++ ){
      x = mspace * ( i%3 + 1 ) + mcellradius + mcellwidth * ( i%3 ) ;
      y = mspace * ( i/3 + 1 ) + mcellradius + mcellwidth * ( i/3 ) ;
      cell = new cell(x , y);
      mcells[i] = cell ;
    }
  }
  @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    drawcell(canvas);
    drawline(canvas);
  }
  //绘制连接线
  private void drawline( canvas canvas ){
    if("".equals(msbselected.tostring())){
      return;
    }
    string[] selectedindexs = msbselected.tostring().split(",");
    cell cell = mcells[integer.valueof(selectedindexs[0])];
    cell nextcell ;
    //绘制每两个格子中心点之间的连接线
    if( selectedindexs.length > 1) {
      for (int i = 1; i < selectedindexs.length; i++) {
        nextcell = mcells[integer.valueof(selectedindexs[i])];
        canvas.drawline(cell.getcenterx(), cell.getcentery(), nextcell.getcenterx(), nextcell.getcentery(), mpaintselected);
        cell = nextcell;
      }
    }
    //绘制格子到其他空白位置的连接线
    if( !mfinish ) {
      canvas.drawline(cell.getcenterx(), cell.getcentery(), mcurrentx, mcurrenty, mpaintselected);
    }
  }
  private void drawcell( canvas canvas ){
    for ( int i = 0 ; i < 9 ; i ++ ){
      canvas.drawcircle(mcells[i].getcenterx(), mcells[i].getcentery() , mcellradius ,
          mcells[i].isselected() ? mpaintselected : mpaintnormal );
    }
  }
  //处理点击事件
  @override
  public boolean ontouchevent(motionevent event) {
    switch ( event.getaction()){
      case motionevent.action_down:
        //如果手指已经松开,则所有格子变为初始状态
        if( mfinish ){
          for ( int i = 0 ; i < 9 ; i ++ ){
            mcells[i].setselected(false);
          }
          mfinish = false ;
          msbselected.delete(0,msbselected.length());
          invalidate();
          return false;
        }
        handledownevent(event);
        break;
      //松开则结束
      case motionevent.action_up:
        mfinish = true ;
        break;
      case motionevent.action_move:
        handlemoveevent(event);
        break;
    }
    //表示已处理,不向上传递
    return true ;
  }
  //处理手指移动的事件
  private void handlemoveevent( motionevent event ){
    int index = findcellindex(event.getx(),event.gety());
    if( index != -1 ){
      mcells[index].setselected(true);
      msbselected.append(index).append(",");
    }
    invalidate();
    mcurrentx = event.getx();
    mcurrenty = event.gety();
  }
  //处理手指按下的事件
  private void handledownevent( motionevent event){
    int index = findcellindex(event.getx(),event.gety());
    if( index != -1 ){
      mcells[index].setselected(true);
      msbselected.append(index).append(",");
      invalidate();
    }
    mcurrentx = event.getx();
    mcurrenty = event.gety();
  }
  //根据坐标判断点击的哪个格子
  private int findcellindex( float x , float y){
    float cellx ;
    float celly ;
    int result = -1 ;
    for( int i = 0 ; i < 9 ; i ++ ){
      if( mcells[i].isselected()){
        continue;
      }
      //获取每个格子的坐标
      cellx = mcells[i].getcenterx();
      celly = mcells[i].getcentery();
      //计算按下的点到每个格子的距离
      float tempx = cellx - x ;
      float tempy = celly - y ;
      float distance = (float) math.sqrt(tempx * tempx + tempy * tempy);
      //如果点击的位置在某个格子的圆内
      if( distance < mcellradius ){
        result = i ;
        break;
      }
    }
    //返回该格子的位置
    return result ;
  }
}

最后在布局文件中引用该view即可,若想实现更高的定制性,可以仿照上一篇文章重写view的onmearsure方法并增加自定义属性。

以上所述是小编给大家介绍的android 自定义九宫格手势锁,希望对大家有所帮助