preface

Android custom View skill is necessary to become a senior engineer, I feel that there is no shortcut to custom View, only practice to solve the product needs. The author has not written a custom View for a long time, and quickly wrote a control to find a sense of return.

this article implements a custom control of a lock screen pattern. The results are as follows:

Github address: AndroidSample

reference:

(1) introduced in the layout file. OrmalColor= "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " Integer> intList = new ArrayList< > (); intList.add (3); intList.add (7); intList.add (4); intList.add (2); lockView.setStandard (intList); lockView.setOnDrawCompleteListener. MakeText (CustomViewActivity.this, isSuccess? "Success": "fail", Toast.LENGTH_SHORT).Show ();}});

implements the

  1. to draw a circle with the default state, and the outer color requires a certain degree of transparency in the inner circle color. In the onTouchEvent () method,
  2. determines whether the distance between the current touch point and the circle of the circle is less than the radius of the circle, and determines which state of the circle at this time (normal, move, error), and calls invalidate () to redraw and update the color.
  3. adds the coordinates of the fingers slid through the circle into a ArrayList, and uses the Path to connect the selected circle in the set to draw a crossed path line.

implementation

custom attribute

in the res/values directory; Attr name= "normalColor" format= "color|reference" /> <! - default circle color --> < attr name=. Attr name= "rowCount" format= "integer" /> <! -- the number of each row per row --> < /declare-styleable> < /resources> Blic LockView (Context context, @Nullable AttributeSet attrs) {super (context, attrs); readAttrs (context,);} / * * * / * * .styleable.LockView); normalColor = typedArray.getColor (R.styleable.LockView_normalColor, DEFAULT_NORMAL_COLOR); moveColor = typedArray.getColor (R.styleable.LockView_moveColor, DEFAULT_MOVE_COLOR); errorColor = typedArray.getColor (R.styleable.LockView_errorColor,); OwCount = typedArray.getInteger (R.styleable.LockView_rowCount, DEFAULT_ROW_COUNT); typedArray.recycle ();} / * * * / * * initialization of * / private void init () {stateSparseArray = new SparseIntArray (rowCount *); (Paint.ANTI_ALIAS_FLAG); innerCirclePaint.setStyle (Paint.Style.FILL); outerCirclePaint = new Paint (Paint.ANTI_ALIAS_FLAG); outerCirclePaint.setStyle (Paint.Style.FILL); linePaint = new Paint. Int.Cap.ROUND); linePaint.setStrokeJoin (Paint.Join.ROUND); linePaint.setStrokeWidth (30); linePaint.setColor (moveColor);}

calculates the radius of the circle and sets the outer radius of the circle to the same distance between the adjacent circle, and the inner circle radius is the outer circle. The radius is half, so the radius calculation is:

 radius = Math.min (W, H) / (2 * rowCount + rowCount - 1) * 1.0F; 

 @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure. Height = getSize (heightMeasureSpec); setMeasuredDimension (width, height);} private int getSize (int measureSpec) {int} = {} .AT_MOST) {return Math.min (size, dp2Px (600));} return dp2Px (600);}

 private PointF touchPoint; @Override public Boolean onTouchEvent. T.getY ());} else {touchPoint.set (event.getX (), event.getY ());} for (int i = 0; I < rowCount * rowCount;) {/ / / /} {} Contains (points[i])) {selectedList.add (points[i]);} break;} break; case MotionEvent.ACTION_UP: if (check ()) {/ / / / correct pattern if (listener! =);} {} Int index = stateSparseArray.keyAt (I); stateSparseArray.put (index, STATE_MOVE);} else {/ / / / / / / / error pattern for (int i = 0; I); {} Aint.setColor (0xeeff0000); if (listener! = null) {listener.onComplete (false);} touchPoint = null; if (timer = = null) {} {} {} {};} .setColor (0xee0000ff); selectedList.clear (); stateSparseArray.clear (); postInvalidate ();}, 1000); break;} invalidate (); return true;}

draws connections between circles and circles. NDraw (canvas); drawCircle (canvas); drawLinePath (canvas);} private void drawCircle (Canvas canvas) {/ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / Canvas canvas) {/ / / / / / / / / / / / / / / / / / / / / / / / / / / / Canvas canvas) {/ / / / / / / / / / / / / / / / / / / / / / / drawLinePath) {/ / / / / / / / / / / / / / / / / / / / drawLinePath) {/ / / / / E) {case STATE_NORMAL: innerCirclePaint.setColor (normalColor); outerCirclePaint.setColor (normalColor & 0x66ffffff); break; case STATE_MOVE:. RROR: innerCirclePaint.setColor (errorColor); outerCirclePaint.setColor (errorColor & 0x66ffffff); break;} canvas.drawCircle (points[index].x, points[index].y, radius); }}

complete View Code:

 / * * Created by star.tao on 2018/5/30. * email: xing-java@foxmail.com * OVE_COLOR = 0xee0000ff; private static final int DEFAULT_ERROR_COLOR = 0xeeff0000; private static final int = 0; Slide the default color private int moveColor; / / / / / / / / / / / / / / / / / / / / / / private int errorColor; / / / / / / / / / / / / / / / (/ /) private int rowCount; / / / / one dimension array records the coordinates of all round points; / / / inner circle brush Ate Paint outerCirclePaint; / / private SparseIntArray stateSparseArray; private List< PointF> selectedList = new ArrayList< Private Paint linePaint; private Timer timer; public LockView (Context context) {this (Context,});}


This concludes the body part