自定义view
public class SudokuView extends View {
private Paint mCirclePaint;
private Paint mLinePaint;
private PointView[ ] [ ] mPointViewArray = new PointView [ 3 ] [ 3 ] ;
private List< PointView> mSelectedPointViewList;
private int mPatternWidth;
private OnPatternChangeListener mOnPatternChangeListener;
private float mRadius;
private int mIndex = 1 ;
private boolean mIsSelected;
private boolean mIsFinished;
private boolean mIsMovingWithoutCircle = false ;
private float mCurrentX, mCurrentY;
private static final int NORMAL_COLOR = 0xFF70DBDB ;
private static int SELECTED_COLOR = 0xFF979797 ;
public SudokuView ( Context context ) {
super ( context) ;
}
public SudokuView ( Context context, @Nullable AttributeSet attrs ) {
super ( context, attrs) ;
mCirclePaint = new Paint ( ) ;
mCirclePaint. setAntiAlias ( true ) ;
mCirclePaint. setDither ( true ) ;
mCirclePaint. setColor ( NORMAL_COLOR ) ;
mCirclePaint. setStyle ( Paint. Style. FILL ) ;
mLinePaint = new Paint ( ) ;
mLinePaint. setAntiAlias ( true ) ;
mLinePaint. setDither ( true ) ;
mLinePaint. setStrokeWidth ( 20 ) ;
mLinePaint. setColor ( SELECTED_COLOR ) ;
mLinePaint. setStyle ( Paint. Style. STROKE ) ;
mRadius = TypedValue. applyDimension ( TypedValue. COMPLEX_UNIT_DIP , 20 , getResources ( ) . getDisplayMetrics ( ) ) ;
mSelectedPointViewList = new ArrayList < > ( ) ;
}
@Override
protected void onMeasure ( int widthMeasureSpec, int heightMeasureSpec ) {
super . onMeasure ( widthMeasureSpec, heightMeasureSpec) ;
mPatternWidth = Math. min ( getMeasuredWidth ( ) , getMeasuredHeight ( ) ) ;
setMeasuredDimension ( mPatternWidth, mPatternWidth) ;
}
@Override
protected void onDraw ( Canvas canvas ) {
drawCircle ( canvas) ;
for ( PointView pointView : mSelectedPointViewList) {
mCirclePaint. setColor ( SELECTED_COLOR ) ;
canvas. drawCircle ( pointView. x, pointView. y, mRadius, mCirclePaint) ;
mCirclePaint. setColor ( NORMAL_COLOR ) ;
}
if ( mSelectedPointViewList. size ( ) > 0 ) {
Point pointViewA = mSelectedPointViewList. get ( 0 ) ;
for ( int i = 0 ; i < mSelectedPointViewList. size ( ) ; i++ ) {
Point pointViewB = mSelectedPointViewList. get ( i) ;
drawLine ( canvas, pointViewA, pointViewB) ;
pointViewA = pointViewB;
}
if ( mIsMovingWithoutCircle & ! mIsFinished) {
drawLine ( canvas, pointViewA, new PointView ( ( int) mCurrentX, ( int) mCurrentY) ) ;
}
}
super . onDraw ( canvas) ;
}
private void drawCircle ( 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, mCirclePaint) ;
mIndex++ ;
}
}
mIndex = 1 ;
}
@Override
public 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 ( ) ;
mIsFinished = 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 :
mIsFinished = true ;
mIsSelected = false ;
break ;
}
if ( ! mIsFinished && mIsSelected && selectedPointView != null ) {
if ( ! mSelectedPointViewList. contains ( selectedPointView) ) {
mSelectedPointViewList. add ( selectedPointView) ;
}
}
if ( mIsFinished) {
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 ;
}
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 x, float y, float cx, float cy, float radius ) {
if ( Math. sqrt ( Math. pow ( x - cx, 2 ) + Math. pow ( y - cy, 2 ) ) <= radius) {
return true ;
}
return false ;
}
public void setOnPatternChangeListener ( OnPatternChangeListener onPatternChangeListener ) {
if ( onPatternChangeListener != null ) {
this . mOnPatternChangeListener = onPatternChangeListener;
}
}
private void drawLine ( Canvas canvas, Point pointA, Point pointB ) {
canvas. drawLine ( pointA. x, pointA. y, pointB. x, pointB. y, mLinePaint) ;
}
public void error ( ) {
SELECTED_COLOR = Color. RED ;
mLinePaint. setColor ( SELECTED_COLOR ) ;
}
public void access ( ) {
SELECTED_COLOR = Color. GREEN ;
mLinePaint. setColor ( SELECTED_COLOR ) ;
}
public void clear ( ) {
mIsFinished = false ;
SELECTED_COLOR = 0xFF979797 ;
mLinePaint. setColor ( SELECTED_COLOR ) ;
mSelectedPointViewList. clear ( ) ;
invalidate ( ) ;
}
public interface OnPatternChangeListener {
void onPatternChange ( String patternPassword) ;
void onPatternStarted ( boolean isStarted) ;
}
}
圆点类
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
public class MainActivity extends AppCompatActivity implements SudokuView. OnPatternChangeListener {
public SudokuView sudokuView;
public TextView textView;
public Handler handler;
@Override
protected void onCreate ( Bundle savedInstanceState ) {
super . onCreate ( savedInstanceState) ;
setContentView ( R . layout. activity_main) ;
sudokuView = findViewById ( R . id. sudoku_view) ;
textView = findViewById ( R . id. tv_password) ;
sudokuView. setOnPatternChangeListener ( this ) ;
handler = new Handler ( ) ;
}
@Override
public void onPatternChange ( String patternPassword ) {
if ( patternPassword == null ) {
textView. setText ( "至少5个点" ) ;
sudokuView. error ( ) ;
} else if ( patternPassword. equals ( "123654789" ) ) {
textView. setText ( patternPassword) ;
sudokuView. access ( ) ;
} else {
textView. setText ( patternPassword) ;
sudokuView. error ( ) ;
}
handler. postDelayed ( new Runnable ( ) {
public void run ( ) {
textView. setText ( "" ) ;
sudokuView. clear ( ) ;
}
} , 500 ) ;
}
@Override
public void onPatternStarted ( boolean isStarted ) {
if ( isStarted) {
textView. setText ( "请绘制图案" ) ;
} else {
}
}
}