Acerca del visor de Android para implementar la interacción de tarjetas apiladas

fondo

Las olas detrás del río Yangtze empujan las olas hacia adelante y las demandas aburridas se suceden una tras otra.
Recientemente, se me ocurrió un requisito sobre el apilamiento de tarjetas, que me pareció bastante interesante, así que lo registraré aquí.

El enlace del código fuente se adjuntará al final del artículo.

Primero mire el dibujo del diseño:
Insertar descripción de la imagen aquí
puede ver que es un efecto de apilamiento de tarjetas. Hay muchas formas de implementar esta interfaz de usuario, como usar recyclerview, viewpager o incluso una vista personalizada. Este artículo describirá cómo usar viewpager para lograr esto. ... tipo de efecto.

entorno de desarrollo

win10
jdk 8
como 4+

lograr efecto

Insertar descripción de la imagen aquí
Dado que es una demostración, no es necesario prestar demasiada atención al color, solo implemente las funciones básicas.

pregunta

1. Cómo modificar la posición de apilamiento de una tarjeta en el visor
2. Cómo modificar dinámicamente el ancho y alto de la tarjeta durante el proceso de deslizamiento

Ideas

Para el visor, existe una propiedad ViewPager.PageTransformer ¿Para qué se utiliza esta propiedad?
Eche un vistazo a la descripción del código fuente:

    /**
     * A PageTransformer is invoked whenever a visible/attached page is scrolled.
     * This offers an opportunity for the application to apply a custom transformation
     * to the page views using animation properties.
     *
     * <p>As property animation is only supported as of Android 3.0 and forward,
     * setting a PageTransformer on a ViewPager on earlier platform versions will
     * be ignored.</p>
     */
    public interface PageTransformer {
        /**
         * Apply a property transformation to the given page.
         *
         * @param page Apply the transformation to this page
         * @param position Position of page relative to the current front-and-center
         *                 position of the pager. 0 is front and center. 1 is one full
         *                 page position to the right, and -1 is one page position to the left.
         */
        void transformPage(@NonNull View page, float position);
    }

En pocas palabras, controla la entrada y salida de la página. De una manera simple, puede usar esta clase para lograr el efecto de entrar y salir de algunas páginas del visor. Para una más complicada, puede calcular dinámicamente un atributo de control de la vista relacionada durante el proceso de deslizamiento del visor, etc.

A través de la herencia, herede PageTransformer para implementar una subclase y anule el
método void transformPage(@NonNull View page, float position);
En este método, el primer parámetro es el objeto de vista deslizante. El segundo parámetro es la posición de deslizamiento relativa de la vista. Cabe señalar aquí que no es la posición de la vista en el visor, sino simplemente una posición deslizante, que puede entenderse simple y crudamente como
"negativo derecho, positivo, izquierdo, cero, medio". Cuando la posición es 0, es la vista que se muestra actualmente. De manera similar, -1 está a la izquierda de 0 y 1 está a la derecha de 0. Como se muestra en la figura siguiente
Insertar descripción de la imagen aquí
, el 0 aquí es relativo a la posición igual a 0.

Lo anterior es una descripción de la situación de devolución de llamada de parámetros en el método transformPage.

---------------------------------Línea divisoria--------------- -----------------------

Ahora que tenemos el objeto de vista y las devoluciones de llamada para la posición deslizándose hacia la izquierda y hacia la derecha, podemos hacer muchas cosas. En primer lugar, el valor de la posición se ve afectado por el deslizamiento hacia la izquierda y hacia la derecha del visor: el deslizamiento hacia la derecha es un número negativo y el deslizamiento hacia la izquierda es un número positivo. ¡En este momento, puedes realizar algunas conversiones de tamaño de control deslizándote hacia la izquierda y hacia la derecha!
Tenga en cuenta que durante el procesamiento de datos, afectan los valores positivos y negativos de la posición.

lograr

1. Implemente el apilamiento de tarjetas del visor. ¡
A través de setTranslationX, puede establecer la posición x de la vista!
¡A través de LayoutParams, puede establecer el margen derecho de la vista!


Imagine establecer un valor negativo a través de setTranslationX. ¿Es posible colocar la vista en la segunda posición del visor directamente en la posición de la primera vista? Simplemente significa que después de colocarlo, seguirá bloqueado por la primera vista, haciéndolo invisible. Por analogía, la posición de la vista en un visor se completa.


Ir a LayoutParams ¿no es cuestión de dar puntos? ¿No es posible establecer directamente el margen correcto según la posición?


A estas alturas creo que la mayoría de la gente ya lo entiende.
No importa si no lo entiendes, puedes echar un vistazo al siguiente código:


    @Override
    public void transformPage(@NonNull View view, float position) {
        int pagerWidth = boundViewPager.getWidth();
        LogUtil.d("transformPage tag: " + view.hashCode() + " pos: " + position + " pagerWidth: " + pagerWidth);
        float scaleWidth = pagerWidth * CENTER_PAGE_SCALE;
        float widthInterval = (pagerWidth - scaleWidth) / 2;

        view.setScaleX(CENTER_PAGE_SCALE);
        view.setScaleY(CENTER_PAGE_SCALE);

        //设置间距----------------------------------------------------------------------
        ViewGroup llRoot = view.findViewById(R.id.llRoot);
        if (llRoot != null) {
            ViewGroup.LayoutParams layoutParams = llRoot.getLayoutParams();
            if (layoutParams instanceof RelativeLayout.LayoutParams) {
                ((RelativeLayout.LayoutParams) layoutParams).setMarginEnd((int) ((2 - Math.abs(position)) * endInterval));
                ((RelativeLayout.LayoutParams) layoutParams).topMargin = (int) (Math.abs(position) * verticalInterval);
                ((RelativeLayout.LayoutParams) layoutParams).bottomMargin = (int) (Math.abs(position) * verticalInterval);
                llRoot.setLayoutParams(layoutParams);
            } else if (layoutParams instanceof CardView.LayoutParams) {
                ((FrameLayout.LayoutParams) layoutParams).setMarginEnd((int) ((2 - Math.abs(position)) * endInterval));
                ((FrameLayout.LayoutParams) layoutParams).topMargin = (int) (Math.abs(position) * verticalInterval);
                ((FrameLayout.LayoutParams) layoutParams).bottomMargin = (int) (Math.abs(position) * verticalInterval);
                llRoot.setLayoutParams(layoutParams);
            }
        }
        //设置偏移量----------------------------------------------------------------------
        if (position >= 0) {
            view.setTranslationX(-pagerWidth * position);
        }
        if (position > -1 && position < 0) {
            view.setAlpha((position * position * position + 1));
        } else if (position > offscreenPageLimit - 1) {
            view.setAlpha((float) (1 - position + Math.floor(position)));
        } else {
            view.setAlpha(1);
        }
    }
}

Simple y claro, se pueden lograr dos métodos.
Bien, ahora que se logra la interacción, ¡todavía hay un problema de "bucle infinito"!
No hay más que dos soluciones: una es configurar el adaptador getCount en infinito y la otra es crear una diferencia visual para el usuario complementando los datos antes y después. Pero cuando se trata de nuestra implementación aquí, el primer método es obviamente más apropiado. No hay mucho que decir aquí.


Finalmente, dirección del código fuente: Dirección del código
Buscar clase VPTestActivity

eso es todo------------------------------------------------ --------------------------------------------------

Supongo que te gusta

Origin blog.csdn.net/motosheep/article/details/131017260
Recomendado
Clasificación