Desarrollo de Android: TabLayout personalizado, el efecto mágico es tan simple

Prefacio

No digas nada, primero muestra las representaciones:

Recientemente, la interfaz de usuario de la empresa diseñó un estilo de cambio de pestaña de este tipo. Tan pronto como vi el dibujo de diseño de la interfaz de usuario, me sentí bastante bien. Pero después de unos segundos, inconscientemente pensé que este efecto, el control de tablayout que viene con Android no debería poder lograr este efecto. De repente miré una pérdida, ¡todavía tengo que personalizar una! Pero, ¿qué pasa con este arco ...

En este momento, algunos amigos pueden pensar que personalizar la vista es demasiado problemático. Es mejor dejar que la interfaz de usuario corte directamente este arco. Hay tres elementos de pestaña en total, Textview, ImageView ... De esta manera, organícelos horizontalmente, y luego haga la visualización adecuada y simplemente ocúltelo.

Sí, de hecho es posible, pero como buen desarrollador. Todavía tenemos que preferir las vistas personalizadas.

Análisis de pensamiento

(1) A partir del diagrama de efectos, podemos analizar fácilmente que no importa cuántos elementos de pestaña haya, solo existen estas tres situaciones.
El croquis es el siguiente:

(2) En cualquier caso, primero necesitamos dibujar un rectángulo de fondo, que es relativamente simple.

(3) El siguiente es el método de dibujo de la curva, que se ha marcado en el boceto. Obviamente necesito 2 puntos de control, ¡así que necesito usar una curva Bezier de tercer orden! cubicTo

(4) Después de dibujar el gráfico, ¿cómo responder al evento de clic? Podemos obtener las coordenadas xey después de hacer clic en el control en onTouchEvent, y podemos juzgar en qué elemento de pestaña se encuentra la coordenada x, y pensamos que se hizo clic en el elemento de pestaña.

(5) ¿Cómo realizar las esquinas redondeadas del control? El lienzo se puede recortar.

Código

Después de ordenar las ideas, escribamos el código:

Situación uno (código clave):

 //最左边的图形
            Path pathLeft = new Path();


            pathLeft.lineTo(textWidth, 0);

            pathLeft.cubicTo(textWidth + arcControlX, arcControlY, textWidth + arcWidth - arcControlX, viewHeight - arcControlY, textWidth + arcWidth, viewHeight);

            pathLeft.lineTo(0, viewHeight);

            pathLeft.lineTo(0, 0);


            paint.setColor(selectColor);
            canvas.drawPath(pathLeft, paint);

Descripción del paso:

  1. Primero, las coordenadas de nuestro punto de partida son (0, 0), y dibuja una línea recta hacia las coordenadas (textWidth, 0);
  2. Luego, la curva Bézier de tercer orden, las coordenadas de los dos puntos de control son 1 (textWidth + arcControlX, arcControlY), coordenadas 2 (textWidth + arcWidth-arcControlX, viewHeight-arcControlY) y las coordenadas finales (textWidth + arcWidth, viewHeight) ;
  3. Finalmente, dibuje una línea recta hasta el punto de coordenadas (0, viewHeight) y luego hasta el origen final (0, 0).

Un camino cerrado aquí, solo dibujalo. Lo mismo es cierto en el caso dos y en el caso tres, y ya no diré tonterías.

Situación dos (código clave):

 //中间的图形
            Path pathCenter = new Path();
            pathCenter.moveTo(tabPosition * textWidth + tabPosition * arcWidth, 0);
            pathCenter.cubicTo(tabPosition * textWidth + tabPosition * arcWidth - arcControlX, arcControlY, tabPosition * textWidth + tabPosition * arcWidth - arcWidth + arcControlX, viewHeight - arcControlY, tabPosition * textWidth + tabPosition * arcWidth - arcWidth, viewHeight);
            pathCenter.lineTo(tabPosition * textWidth + tabPosition * arcWidth + textWidth + arcWidth, viewHeight);
            pathCenter.cubicTo(tabPosition * textWidth + tabPosition * arcWidth + textWidth + arcWidth - arcControlX, viewHeight - arcControlY, tabPosition * textWidth + tabPosition * arcWidth + textWidth + arcControlX, arcControlY, tabPosition * textWidth + tabPosition * arcWidth + textWidth, 0);
            pathCenter.lineTo(tabPosition * textWidth + tabPosition * arcWidth, 0);


            paint.setColor(selectColor);
            canvas.drawPath(pathCenter, paint);

Situación tres (código clave):

  //最右边的图形
            Path pathRight = new Path();
            pathRight.moveTo(viewWidth, 0);

            pathRight.lineTo(viewWidth - textWidth, 0);


            pathRight.cubicTo(viewWidth - textWidth - arcControlX, arcControlY, viewWidth - textWidth - arcWidth + arcControlX, viewHeight - arcControlY, viewWidth - textWidth - arcWidth, viewHeight);

            pathRight.lineTo(viewWidth, viewHeight);

            pathRight.lineTo(viewWidth, 0);

            paint.setColor(selectColor);
            canvas.drawPath(pathRight, paint);

Dibujo de tabtext (código clave):

for (int i = 0; i < tabTextList.size(); i++) {
            String strTabText = tabTextList.get(i);
            Rect rectText = new Rect();
            textPaint.getTextBounds(strTabText, 0, strTabText.length(), rectText);
            int strWidth = rectText.width();
            int strHeight = rectText.height();
            if (i == 0) {
                canvas.drawText(strTabText, (textWidth + arcWidth / 2) / 2 - strWidth / 2, viewHeight / 2 + strHeight / 2, textPaint);
            } else if (i == tabTextList.size() - 1) {
                canvas.drawText(strTabText, viewWidth - (textWidth + arcWidth / 2) / 2 - strWidth / 2, viewHeight / 2 + strHeight / 2, textPaint);

            } else {
                canvas.drawText(strTabText, textWidth * i + arcWidth * (i - 1) + (textWidth + 2 * arcWidth) / 2 - strWidth / 2, viewHeight / 2 + strHeight / 2, textPaint);
            }

        }

Procesamiento de clic de tabulación (código clave):

@Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean isHandleClick = false;//是否处理点击事件

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                float x = event.getX();
                float y = event.getY();
                System.out.println("YPKTabLayoutView.onTouchEvent x=" + x + " y=" + y);
                for (int i = 0; i < tabNumber; i++) {
                    if (x <= ((i + 1) * textWidth + i * arcWidth + arcWidth / 2)) {//点击的第一个按钮
                        tabPosition = i;

                        if (onTabClickListener != null) {
                            onTabClickListener.tabSelectedListener(tabPosition);
                        }

                        invalidate();
                        isHandleClick = true;

                        break;
                    }
                }

                return isHandleClick;


            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return super.onTouchEvent(event);
    }

Descripción del paso:

En el método onTouchEvent, primero obtenemos las coordenadas xey después de hacer clic en el control, y luego el bucle for determina en qué elemento de pestaña se encuentra la coordenada x y, finalmente, en qué rango, creemos que se hace clic en el elemento de pestaña y el callback corresponde La tabPosition servirá.

Uso dependiente remoto

Uno: agregar dependencia

Agréguelo en su build.gradle raíz al final de los repositorios:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Agrega la dependencia

dependencies {
      implementation 'com.github.dacaoyuan:YPKTabDemo:1.0.2'
}

Dos: agregue el diseño xml

<com.ypk.library.view.YPKTabLayoutView
        android:id="@+id/mYPKTabLayoutView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        app:view_bg_corners="0"
        app:arcControlX="30" />

Tres: en el código

val tabTextList: MutableList<String> = ArrayList<String>()

        tabTextList.add("推荐学习");
        tabTextList.add("企业学院");
        tabTextList.add("我的关注");
        mYPKTabLayoutView.setTabTextList(tabTextList);

        mYPKTabLayoutView.addTabSelectedListener { tabPosition ->
            val makeText =
                Toast.makeText(
                    this@MainActivity,
                    "点击了第" + tabPosition + "项",
                    Toast.LENGTH_SHORT
                )
            makeText.setGravity(Gravity.CENTER, 0, 0);
            makeText.show();
        }

Descripción de propiedad

El artículo está aquí, si tienes mejores sugerencias para la realización de ideas, por favor deja un mensaje y corrígeme.

Dirección de la fuente:

https://github.com/dacaoyuan/YPKTabDemo

Al final

Aquí también comparto un PDF de aprendizaje de Android + video de arquitectura + documento de entrevista + notas de origen , mapa mental avanzado de tecnología de arquitectura avanzada, materiales especiales de entrevistas de desarrollo de Android, materiales de arquitectura avanzada avanzada recopilados y organizados por varios grandes .

Estos son materiales excelentes que leeré una y otra vez en mi tiempo libre. Puede ayudar eficazmente a todos a dominar el conocimiento y a comprender los principios. Por supuesto, también puede utilizarlo para comprobar si hay omisiones y mejorar su competitividad.

Si lo necesitas, puedes  conseguirlo aquí

Si te gusta este artículo, también puedes darme un pequeño me gusta, dejar un mensaje en el área de comentarios o reenviarlo y apoyarlo ~

Supongo que te gusta

Origin blog.csdn.net/River_ly/article/details/107228575
Recomendado
Clasificación