Android custom view (6) handwritten a fun alphabet

Time:2022-5-14
Look at the effect first
Android custom view (6) handwritten a fun alphabet

Screenrecorder-2021-06-29-14-25-54-6992021629143911.gif

Write in two steps

(1) Draw 26 letters from top to bottom
(2) Intercept the touch event, change the x position of several adjacent letters according to the finger contact, and redraw the letters.

(1) Draw 26 letters

The first step is to draw 26 letters from top to bottom. This is simple. Use the for loop to draw from top to bottom. Text drawing can refer to:(Android custom view series (1) – draw text to implement a simple textview (foundation of custom view) – developeppaper (Jianshu. Com)

The 26 letter drawing code is as follows:

for (int i = 0; i < lettersList.length; i++) {
            //Calculate the center in the Y direction of each item
            int itemCenterY = itemHeight * i + itemHeight / 2 + getPaddingTop();
            //The position of the baseline is equal to the position of the midline + dy
            int baseLine = itemCenterY + dy;
            canvas.drawText(lettersList[i], x, baseLine, normalPaint);
        }

The position of X remains unchanged, itemcenter is incremented, and the baseline of each letter can be obtained by cycling.

(2) Monitor and intercept touch events, and change the position of adjacent letters in the X direction according to the contact

After obtaining the point of the finger, change the position of several adjacent letters in the X direction of the contact, and then redraw. Repeat this to achieve the effect in the figure. Event listening Code:

@SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //Reduce touch area
        if (event.getX() < (getWidth() - 2 * getPaddingRight() - normalPaint.measureText(lettersList[0]))) {
            if (!((currentY == -1) && (currentPosition == -1))) {
                currentY = -1;
                currentPosition = -1;
                invalidate();
            }
            return false;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                //Get the value of the current contact y and divide it by the height of item to get the position of the contact
                currentY = event.getY();
                int itemHeight = getHeight() / lettersList.length;
                int newPosition = (int) (currentY / itemHeight);
                //Prevent array out of bounds
                if (newPosition < 0) newPosition = 0;
                if (newPosition > lettersList.length - 1) newPosition = lettersList.length - 1;
                //Rendering optimization to prevent unnecessary repeated rendering
                if (newPosition == currentPosition) return true;
                currentPosition = newPosition;
                if (mLetterChangeListener != null) {
                    mLetterChangeListener.letterChange(lettersList[currentPosition], false);
                }
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                currentY = -1;
                if (mLetterChangeListener != null) {
                    mLetterChangeListener.letterChange(lettersList[currentPosition], true);
                }
                invalidate();
                break;
            default:
                currentY = -1;
                currentPosition = -1;
                invalidate();
                break;
        }
        return true;
//        return super. onTouchEvent(event); //  Return true means to intercept subsequent events. If false, the move event will not be intercepted again
    }

You can see that each event trigger will record the y value currenty of the current contact and the position CurrentPosition of the currently selected letter, and call the invalidate () method to redraw.
After the touch event is triggered, the code of letter redrawing is as follows:

for (int i = 0; i < lettersList.length; i++) {
            //Calculate the center in the Y direction of each item
            int itemCenterY = itemHeight * i + itemHeight / 2 + getPaddingTop();

            //The position of the baseline is equal to the position of the midline + dy
            int baseLine = itemCenterY + dy;

            //Move the x position of several items adjacent to the selected item to the left
            If ((current > 0) & & (math.abs (current - itemcenter) < 3 * itemheight)) {// Note 1
                If (I = = CurrentPosition) {// selected item
                    canvas.drawText(lettersList[i],
                            (float) (x - (3.5 * itemHeight - Math.abs(currentY - itemCenterY))), baseLine, normalPaint);
                    canvas.drawText(lettersList[i],
                            (x - (6 * itemHeight - Math.abs(currentY - itemCenterY))), baseLine, highLinePaint);//  Draw another big one
                }else {
                    canvas.drawText(lettersList[i], x - (3 * itemHeight - Math.abs(currentY - itemCenterY)), baseLine, normalPaint);
                }
            } else {
                canvas.drawText(lettersList[i], x, baseLine, normalPaint);
            }
        }

It can be seen that the condition judgment is added at note 1, and the x position of several letters adjacent to the contact is reduced in turn to form the dynamic effect shown in the figure.
In addition, this alphabetic index can be added to the contact list to make the project complete. The contact list will not be introduced here. If you are interested, you can study the code. Source code:(LetterSeekBar/LettersSeekBar.java at master · EthanLee-88/LetterSeekBar (github.com)