效果图

重写一个view一般情况下只需要重写OnDraw方法。那么什么时候需要重写OnMeasure、OnLayout、OnDraw方法呢,这个问题只要把这几个方法的功能弄清楚你就应该知道怎么做了。

①如果需要改变View绘制的图像,那么需要重写OnDraw方法。(这也是最常用的重写方式。)

②如果需要改变view的大小,那么需要重写OnMeasure方法。

③如果需要改变View的(在父控件的)位置,那么需要重写OnLayout方法。

④根据上面三种不同的需要你可以组合出多种重写方案,你懂的。

LockPatternView

package com.example.liuan.jiugongge;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;import java.util.ArrayList;
import java.util.List;/*** 图案解锁* Name: LockPatternView* Author: liuan* creatTime:2017-01-11 20:45*/public class LockPatternView extends View {// 正常状态的颜色private static final int SELECTED_COLOR = 0xFF979797;// 正常状态的颜色private static final int NORMAL_COLOR = 0xFF70DBDB;private Paint mCiclePaint;private Paint mLinePoaint;private float mRadius;//圆心数组private PointView[][] mPointViewArray = new PointView[3][3];//保存选中点的集合private List<PointView> mSelectedPointViewList;//解锁团的边长private int mPatternWidth;//每个圆圈的下标private int mIndex = 1;//正在滑动 并且没有任何点选中private boolean mIsMovingWithoutCircle = false;//是否绘制结束private boolean mIsFinsihed;private float mCurrentX, mCurrentY;//图案监听器private OnPatternChangeListener mOnPatternChangeListener;//第一个点是否选中private boolean mIsSelected;public LockPatternView(Context context) {this(context, null);}public LockPatternView(Context context, AttributeSet attrs) {super(context, attrs);//圆的画笔mCiclePaint = new Paint();mCiclePaint.setAntiAlias(true);mCiclePaint.setDither(true);mCiclePaint.setColor(NORMAL_COLOR);mCiclePaint.setStyle(Paint.Style.FILL);//线的画笔mLinePoaint = new Paint();mLinePoaint.setAntiAlias(true);mLinePoaint.setDither(true);mLinePoaint.setStrokeWidth(20);mLinePoaint.setColor(SELECTED_COLOR);mLinePoaint.setStyle(Paint.Style.STROKE);mRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics());mSelectedPointViewList = new ArrayList<>();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//获取屏幕长和宽中的较小值作为图案的边长mPatternWidth = Math.min(getMeasuredHeight(), getMeasuredWidth());setMeasuredDimension(mPatternWidth, mPatternWidth);}@Overrideprotected void onDraw(Canvas canvas) {//画圆drawCicle(canvas);//将选中的圆 重新绘制一遍  将选中的点和未选中的点区别开来for (PointView pointView : mSelectedPointViewList) {mCiclePaint.setColor(SELECTED_COLOR);canvas.drawCircle(pointView.x, pointView.y, mRadius, mCiclePaint);//每重新绘制一个,将画笔的颜色重置 保证不会影响到其他圆的绘制mCiclePaint.setColor(NORMAL_COLOR);}//点与点画线if (mSelectedPointViewList.size() > 0) {//第一个选中的点为A点Point pointViewA = mSelectedPointViewList.get(0);for (int i = 0; i < mSelectedPointViewList.size(); i++) {//其余的点为B点Point pointViewB = mSelectedPointViewList.get(i);drawLine(canvas, pointViewA, pointViewB);pointViewA = pointViewB;}//点于鼠标当前位置绘制轨迹if (mIsMovingWithoutCircle & !mIsFinsihed) {drawLine(canvas, pointViewA, new PointView((int) mCurrentX, (int) mCurrentY));}}super.onDraw(canvas);}private void drawCicle(Canvas canvas) {//canvas 画布//初始点的位置for (int i = 0; i < mPointViewArray.length; i++) {for (int j = 0; j < mPointViewArray.length; j++) {//圆心坐标int cx = mPatternWidth / 4 * (j + 1);int cy = mPatternWidth / 4 * (i + 1);//将圆心放在一个点数组中PointView pointView = new PointView(cx, cy);pointView.setIndex(mIndex);mPointViewArray[i][j] = pointView;canvas.drawCircle(cx, cy, mRadius, mCiclePaint);mIndex++;}}mIndex = 1;}private void drawLine(Canvas canvas, Point pointA, Point pointB) {canvas.drawLine(pointA.x, pointA.y, pointB.x, pointB.y, mLinePoaint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {mCurrentX = event.getX();mCurrentY = event.getY();PointView selectedPointView = null;switch (event.getAction()) {case MotionEvent.ACTION_DOWN://重新绘制if (mOnPatternChangeListener != null) {mOnPatternChangeListener.onPatternStarted(true);}mSelectedPointViewList.clear();mIsFinsihed = false;selectedPointView = checkSelectPoint();if (selectedPointView != null) {//第一次按下的位置在圆内,被选中mIsSelected = true;}break;case MotionEvent.ACTION_MOVE:if (mIsSelected) {selectedPointView = checkSelectPoint();}if (selectedPointView == null) {mIsMovingWithoutCircle = true;}break;case MotionEvent.ACTION_UP:mIsFinsihed = true;mIsSelected = false;break;}//将选中的点收藏起来if (!mIsFinsihed && mIsSelected && selectedPointView != null) {if (!mSelectedPointViewList.contains(selectedPointView)) {mSelectedPointViewList.add(selectedPointView);}}if (mIsFinsihed) {if (mSelectedPointViewList.size() == 1) {mSelectedPointViewList.clear();} else if (mSelectedPointViewList.size() < 5 && mSelectedPointViewList.size() > 0) {//绘制错误if (mOnPatternChangeListener != null) {mOnPatternChangeListener.onPatternChange(null);}} else {//绘制成功String patternPassword = "";if (mOnPatternChangeListener != null) {for (PointView pointView : mSelectedPointViewList) {patternPassword += pointView.getIndex();}if (!TextUtils.isEmpty(patternPassword)) {mOnPatternChangeListener.onPatternChange(patternPassword);}}}}invalidate();return true;}/*** 判断当前按下的位置是否在圆心数组中** @return 返回选中的点*/private PointView checkSelectPoint() {for (int i = 0; i < mPointViewArray.length; i++) {for (int j = 0; j < mPointViewArray.length; j++) {PointView pointView = mPointViewArray[i][j];if (isWithInCircle(mCurrentX, mCurrentY,pointView.x,pointView.y,mRadius)) {return pointView;}}}return null;}private boolean isWithInCircle(float mCurrentX, float mCurrentY, int x, int y, float mRadius) {//如果点和圆心的距离 小于半径,则证明在圆内if (Math.sqrt(Math.pow(x - mCurrentX, 2) + Math.pow(y - mCurrentY, 2)) < mRadius) {return true;}return false;}public void setOnPatternChangeListener(OnPatternChangeListener onPatternChangeListener) {if (onPatternChangeListener != null) {this.mOnPatternChangeListener = onPatternChangeListener;}}/*** 图案监听器*/public interface OnPatternChangeListener {//图案改变 图案密码patternPasswordvoid onPatternChange(String patternPassword);//图案是否重新绘制void onPatternStarted(boolean isStarted);}
}

PointView

package com.example.liuan.jiugongge;import android.graphics.Point;/*** 自定义点对象* Name: PointView* Author: liuan* creatTime:2017-01-11 21:02*/
public class PointView extends Point{//用于转化密码的下标public int index;public PointView(int x, int y) {super(x, y);}public int getIndex(){return index;}public void setIndex(int index) {this.index = index;}
}

MainActivity

package com.example.liuan.jiugongge;import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;public class MainActivity extends AppCompatActivity implements LockPatternView.OnPatternChangeListener {private LockPatternView lpv;private TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);lpv = (LockPatternView) findViewById(R.id.lock_pattern_view);tv = (TextView) findViewById(R.id.text);lpv.setOnPatternChangeListener(this);}@Overridepublic void onPatternChange(String patternPassword) {if(patternPassword==null){tv.setText("请至少5个点");}else{tv.setText(patternPassword);}}@Overridepublic void onPatternStarted(boolean isStarted) {if(isStarted){tv.setText("请绘制图案");}}
}

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"
android:orientation="vertical"tools:context="com.example.liuan.jiugongge.MainActivity"><TextViewandroid:layout_gravity="center"android:id="@+id/text"android:textColor="#18b968"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="状态显示" /><com.example.liuan.jiugongge.LockPatternViewandroid:clickable="true"android:id="@+id/lock_pattern_view"android:layout_weight="1"android:layout_width="match_parent"android:layout_height="0dp" />
</LinearLayout>

九宫格解锁Android代码相关推荐

  1. 九宫格拼图android代码,Android 多图上传后将图片进行九宫格展示的实例代码

    不多说上代码 public abstract class NineGridAdapter { protected Context context; protected List list; publi ...

  2. 九宫格拼图android代码,九宫格拼图代码

    // //  ViewController.m //  10-拼图 // //  Created by mac on 15-5-9. //  Copyright (c) 2015年itcast. Al ...

  3. Android纯代码实现九宫格解锁

    最近由于Android项目需要,要求做一个类似于支付宝的九宫格解锁组件, 要求不使用美工提供的图片资源,纯代码实现, 我在百度上搜关键字"android九宫格解锁", 终于找到想要 ...

  4. Android之九宫格解锁的实现

    九宫格解锁在Android中应用的很广泛,也是Android特有的一种解锁方式,其实实现起来也并不是很复杂,下面我就根据系统源码LockPatternView,移植出来的一个更加简单小巧九宫格解锁的例 ...

  5. 9宫格解锁 android_Android实现九宫格解锁的实例代码

    当年感觉九宫格解锁很是高大上,一脸懵逼,今天正好要做解锁这一块业务,回头来看九宫格,这特么简单啊 首先理清一下逻辑,我们要做NxN的九宫格 下图是3x3的简单图例 // -(--)-(--)-(--) ...

  6. Android 仿小米锁屏实现九宫格解锁

    最近公司要求做个九宫格解锁,本人用的是小米手机,看着他那个设置锁屏九宫格很好看,就做了该组件,不使用图片资源,纯代码实现. 尊重每个辛苦的博主,在http://blog.csdn.net/mu399/ ...

  7. Android之手势登陆(九宫格解锁)

    前言 上一篇我们介绍了Fragment的使用<Android碎片化布局fragment的实战应用>,其中在登陆的时候会有账号登陆和手势登陆,今天我们就来介绍一下手势登陆的使用,其实这个在网 ...

  8. android 九宫格解锁源码,Android 自己动手实现滑动九宫格解锁

    Android 自己动手实现滑动九宫格解锁 文章主要以实现思路为主.来带领大家逐步实现该效果功能.如有问题,请多多提出 效果预览 整体思路分析 九宫格滑动解锁,为当下比较热门的手机,Pad等触屏设备很 ...

  9. android九宫格布局解锁,Android onDraw()--九宫格解锁

    onDraw这个方法在自定义中尤其重要,我们可以measure之后通过Canvas进行绘制,九宫格解锁这个View现在已经被人脸跟指纹给替代了,但是做起来还是有点东西的. 下面就是做这个View的思路 ...

最新文章

  1. ios Standard Framework和Umbrella Framework
  2. 基于概率论的分类方法—朴素贝叶斯
  3. erlang rebar 配置mysql_Erlang Rebar 使用指南之四:依赖管理
  4. 取代cookie的网站追踪技术:”帆布指纹识别”初探
  5. 【C语言】数据结构C语言版 实验2 不带头结点的单链表
  6. Linux-磁盘及网络IO工作方式解析
  7. linux can设备,Linux CAN编程详解
  8. 面试真题------hashmap与hashset
  9. MIT自动驾驶导航系统,不看地图也能穿梭乡间野路
  10. 常见的javascript日期和时间戳互相转化
  11. 区块链 使用xbench测试xuperchain 教程
  12. unity3d改变物体的中心位置_Unity3d粒子特效:制作火焰效果
  13. 统计项目代码行数工具,如何统计代码行数。
  14. Linux 档案与目录管理
  15. InTouch蜂鸣器报警提示方法
  16. JavaScript 压缩图片
  17. Linux系统-高琪-专题视频课程
  18. SRC——教育漏洞平台
  19. oracle全局索引改成本地索引,解析一个通过添加本地分区索引提高SQL性能的案例...
  20. 服务器芯片市场容量,未来内存接口芯片市场规模 使用内存接口芯片的服务器内存模组主要有寄存内存模组(RDIMM)和减载内存模组(LRDIMM)两种。RDIMM需要一颗寄... - 雪球...

热门文章

  1. 《你一定爱读的极简欧洲史》
  2. linux中'.'的作用
  3. 读书|《静心冥想的练习》:体验超越一切理解的平静与快乐
  4. 通过ReleaseId创建现有项目的KieContainer的时候,提示Cannot find KieModule
  5. 2022春哈工大ICS大作业——程序人生-hello‘sP2P
  6. MFC应用的菜单,工具栏和状态栏(vs2019)
  7. 最优雅高效的 19 条工作习惯 · 职场亮剑
  8. ubuntu显示器分辨率不对_Ubuntu安装事宜之一 — 屏幕分辨率问题
  9. 流利说回购,AI教育面临市场培育的“慢时间”尴尬?
  10. HM不只是到处开实体店了,这次它不想错过天猫新零售