Preface:
If you don't say much, move first.
Preface: These two days, the boss gave a task, saying to be a digital lock screen interface imitating ios, thinking that there should be a lot of such things on the Internet, and then Baidu first, who knows that the case seems to be poor, and then with a skeptical attitude to download the "source code" hard to find, read the inside, and then a little eyebrow, borrow the "source code" themselves. ” The thought has realized one by itself, see the picture above.
Train of thought:
Here we can see two parts, one part is the input above, the other part is the button at the bottom.
Looking at the above section, we can think of it as TextView, and then respond to the action of the button below. In the following section, each button in the picture needs to be drawn by itself. The difficulty is to calculate the coordinates of each button according to the coordinates of the first button (the first coordinate we initialize), and then judge which button is clicked according to the touch screen event of the finger.
Next, let's look at the core code:
The input box section:
public class PasswordTextView extends TextView{ private final String sing = "*";//Content displayed in ciphertext private String content = "";//Content displayed //Text Change Event Callback Interface private OnTextChangedListener onTextChangedListener; /** * Handler Thread object to update the display of the password box * Implementing the display of input as ciphertext */ private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { //Ciphertext display PasswordTextView.this.setText(sing); //Callback Change Event Interface if(onTextChangedListener != null){ onTextChangedListener.textChanged(content); } }; }; /** * Construction method * @param context * @param attrs */ public PasswordTextView(Context context, AttributeSet attrs) { super(context, attrs); } /** * Setting Text Change Event Listener * @param onTextChangedListener */ public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener){ this.onTextChangedListener = onTextChangedListener; } /** * Set the content displayed in the password box * @param text */ public void setTextContent(String text){ //Get input this.content = text; if(!TextUtils.isEmpty(text)){ handler.sendEmptyMessage(0);//Send a message to Handler }else{ this.setText(""); } } /** * Get the content displayed * @return */ public String getTextContent(){ return content; } /** * Text Change Event Interface */ public interface OnTextChangedListener{ /** * Called when the text of the password box changes * @param content */ public void textChanged(String content); } }
The button section below
public class NumericK eyboard extends View { private int screen_width = 0;// Width of screen private float first_x = 0;// Draw x coordinates of 1 private float first_y = 0;// Draw y coordinates of 1 private float[] xs = new float[3];//Declare that the array holds the central abscissa of each column private float[] ys = new float[4];//Declare that the array holds the center coordinates of each row private float circle_x, circle_y;//Centroid coordinates at the click private int number = -1;//Number of clicks private OnNumberClick onNumberClick;//Digital Click Event /* * Judging refresh data * -1 No data refresh * 0 Press refresh * 1 Pop-up refresh */ private int type = -1; /** * Construction method * * @param context */ public NumericKeyboard(Context context) { super(context); initData(context);// Initialization data } public NumericKeyboard(Context context, AttributeSet attrs) { super(context, attrs); initData(context);// Initialization data } /** * Setting Digital Click Events * * @param onNumberClick */ public void setOnNumberClick(OnNumberClick onNumberClick) { this.onNumberClick = onNumberClick; } // Initialization data private void initData(Context context) { // Get the width of the screen screen_width = SystemUtils.getSystemDisplay(context)[0]; // Get the x coordinates of draw 1 first_x = screen_width / 4; // Get y coordinates of plot 1 first_y = (SystemUtils.getSystemDisplay(context)[1] - SystemUtils.getSystemDisplay(context)[1] / 3) / 4; //Add abscissa for each row xs[0] = first_x + 10; xs[1] = first_x * 2 + 10; xs[2] = first_x * 3 + 10; //Add ordinates for each column ys[0] = 40 + first_y - 15; ys[1] = 40 + first_y + first_x - 15; ys[2] = 40 + first_y + first_x * 2 - 15; ys[3] = 40 + first_y + first_x * 3 - 15; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // Create Brush Objects Paint paint = new Paint(); paint.setColor(Color.BLACK);// setpc paint.setTextSize(40);// Set font size paint.setStrokeWidth(2); // Drawing text, note that it starts with coordinates and goes up // The harder part here is to calculate coordinates. // Draw the first row 1, 2, 3 canvas.drawText("1", first_x, 40 + first_y, paint); canvas.drawText("2", first_x * 2, 40 + first_y, paint); canvas.drawText("3", first_x * 3, 40 + first_y, paint); // Draw Row 2 4, 5, 6 canvas.drawText("4", first_x, 40 + first_y + first_x, paint); canvas.drawText("5", first_x * 2, 40 + first_y + first_x, paint); canvas.drawText("6", first_x * 3, 40 + first_y + first_x, paint); // Draw Row 3 7, 8, 9 canvas.drawText("7", first_x, 40 + first_y + first_x * 2, paint); canvas.drawText("8", first_x * 2, 40 + first_y + first_x * 2, paint); canvas.drawText("9", first_x * 3, 40 + first_y + first_x * 2, paint); // Draw Row 4, Row 0 canvas.drawText("0", first_x * 2, 40 + first_y + first_x * 3, paint); //Draw a circle for each number paint.setColor(Color.WHITE);//setpc paint.setAntiAlias(true);//Setting Anti-aliasing //Setting and Drawing Hollow Circle paint.setStyle(Paint.Style.STROKE); //Draw the first row of circles in turn canvas.drawCircle(first_x + 10, 40 + first_y - 15, 70, paint); canvas.drawCircle(first_x * 2 + 10, 40 + first_y - 15, 70, paint); canvas.drawCircle(first_x * 3 + 10, 40 + first_y - 15, 70, paint); //Draw the circles in Row 2 in turn canvas.drawCircle(first_x + 10, 40 + first_y + first_x - 15, 70, paint); canvas.drawCircle(first_x * 2 + 10, 40 + first_y + first_x - 15, 70, paint); canvas.drawCircle(first_x * 3 + 10, 40 + first_y + first_x - 15, 70, paint); //Draw the third row of circles in turn canvas.drawCircle(first_x + 10, 40 + first_y + first_x * 2 - 15, 70, paint); canvas.drawCircle(first_x * 2 + 10, 40 + first_y + first_x * 2 - 15, 70, paint); canvas.drawCircle(first_x * 3 + 10, 40 + first_y + first_x * 2 - 15, 70, paint); //Draw the last circle canvas.drawCircle(first_x * 2 + 10, 40 + first_y + first_x * 3 - 15, 70, paint); //Determine whether to click on a number (the gradient effect of clicking on a number) if (circle_x > 0 && circle_y > 0) { if (type == 0) {//Press refresh paint.setColor(Color.WHITE);//setpc paint.setStyle(Paint.Style.FILL_AND_STROKE);//Draw solid circles when pressed canvas.drawCircle(circle_x, circle_y, 70, paint);//Draw circle } else if (type == 1) {//Pop-up refresh paint.setColor(Color.WHITE);//setpc paint.setStyle(Paint.Style.STROKE);//Draw a hollow circle when it bounces canvas.drawCircle(circle_x, circle_y, 70, paint);//Draw circle //After drawing, reset circle_x = 0; circle_y = 0; } } } /** * Get Touch Click Events */ @Override public boolean onTouchEvent(MotionEvent event) { //Event judgement switch (event.getAction()) { case MotionEvent.ACTION_DOWN://Press down //Determine the coordinate position of the click float x = event.getX();//X-coordinates when pressed float y = event.getY();//Y coordinates when pressed //Determine which numeric circle to click on handleDown(x, y); return true; case MotionEvent.ACTION_UP://Bounce up type = 1;//Pop-up refresh invalidate();//Refresh interface //Return the number of clicks if (onNumberClick != null && number != -1) { onNumberClick.onNumberReturn(number); } setDefault();//Restore default //Send auxiliary events sendAccessEvent(R.string.numeric_keyboard_up); return true; case MotionEvent.ACTION_CANCEL://cancel //Restore default values setDefault(); return true; } return false; } /* * Restore default values */ private void setDefault() { circle_x = 0; circle_y = 0; type = -1; number = -1; sendAccessEvent(R.string.numeric_keyboard_cancel); } /* * Setting up Auxiliary Function Description */ private void sendAccessEvent(int resId) { //Setup description setContentDescription(getContext().getString(resId)); //Send auxiliary events sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); setContentDescription(null); } /* * Determine which numeric circle to click on */ private void handleDown(float x, float y) { //Judging which column of data to click on if (xs[0] - 70 <= x && x <= xs[0] + 70) {//First column //Get the abscissa of the center of the circle at the click circle_x = xs[0]; //Determine which row to click on if (ys[0] - 70 <= y && ys[0] + 70 >= y) {//The first row //Get the center coordinates of the clicked digital circle circle_y = ys[0]; number = 1;//Set the number of clicks } else if (ys[1] - 70 <= y && ys[1] + 70 >= y) {//The second row //Get the center coordinates of the clicked digital circle circle_y = ys[1]; number = 4;//Set the number of clicks } else if (ys[2] - 70 <= y && ys[2] + 70 >= y) {//The third row //Get the center coordinates of the clicked digital circle circle_y = ys[2]; number = 7;//Set the number of clicks } } else if (xs[1] - 70 <= x && x <= xs[1] + 70) {//The second column //Get the abscissa of the center of the circle at the click circle_x = xs[1]; //Determine which row to click on if (ys[0] - 70 <= y && ys[0] + 70 >= y) {//The first row //Get the center coordinates of the clicked digital circle circle_y = ys[0]; number = 2;//Set the number of clicks } else if (ys[1] - 70 <= y && ys[1] + 70 >= y) {//The second row //Get the center coordinates of the clicked digital circle circle_y = ys[1]; number = 5;//Set the number of clicks } else if (ys[2] - 70 <= y && ys[2] + 70 >= y) {//The third row //Get the center coordinates of the clicked digital circle circle_y = ys[2]; number = 8;//Set the number of clicks } else if (ys[3] - 70 <= y && ys[3] + 70 >= y) {//The fourth row //Get the center coordinates of the clicked digital circle circle_y = ys[3]; number = 0;//Set the number of clicks } } else if (xs[2] - 70 <= x && x <= xs[2] + 70) {//The third column //Get the abscissa of the center of the circle at the click circle_x = xs[2]; //Determine which row to click on if (ys[0] - 70 <= y && ys[0] + 70 >= y) {//The first row //Get the center coordinates of the clicked digital circle circle_y = ys[0]; number = 3;//Set the number of clicks } else if (ys[1] - 70 <= y && ys[1] + 70 >= y) {//The second row //Get the center coordinates of the clicked digital circle circle_y = ys[1]; number = 6;//Set the number of clicks } else if (ys[2] - 70 <= y && ys[2] + 70 >= y) {//The third row //Get the center coordinates of the clicked digital circle circle_y = ys[2]; number = 9;//Set the number of clicks } } sendAccessEvent(R.string.numeric_keyboard_down); type = 0;//Press refresh //Draw the background circle when clicking invalidate(); } /** * Digital Click Event */ public interface OnNumberClick { /** * Return the number of clicks * * @param number */ public void onNumberReturn(int number); } }
As mentioned above, the difficulty lies in calculating the position of keys. Here I have modified the calculation method according to the demo I downloaded. If you don't understand the android screen coordinate system, please read the following article: