Realización del efecto de desplazamiento hacia arriba y hacia abajo (marquesina) de Android

Existe un requisito para que el producto se desplace hacia arriba y hacia abajo en el texto. Lo primero que me viene a la mente es usar la animación de atributos para cambiar entre dos TextViews. Leí un montón de materiales en Internet y la mayoría de ellos son TextSwitch. Es realmente melancólico escribir un blog sin publicar las representaciones. No sé el efecto específico, si hay un problema con el primer cambio, si hay un problema con el último cambio al segundo, si la animación es fluida, etc. No puedo ver nada. Entonces, de acuerdo con la primera idea, encontré un enfoque similar, pero parece ser un problema, así que lo modifiqué. El renderizado es el siguiente: (La velocidad de fotogramas del gif es un poco baja, no muy suave y funciona bien en la máquina real)

 

La idea es que los dos TextViews usen la animación de atributos para cambiar hacia arriba y hacia abajo, retrasando el hilo de envío para activar el siguiente desplazamiento.

el código se muestra a continuación:

1.ScrrollTextView.java

import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.lanjinger.choiassociatedpress.R;

import java.util.List;

/**
 * 上下滚动的 textView
 */
public class ScrollTextView extends LinearLayout {
    private TextView mBannerTV1;
    private TextView mBannerTV2;
    private Handler handler;
    private boolean isShow = false;
    private int startY1, endY1, startY2, endY2;
    private Runnable runnable;
    private List<String> list;
    private int position = 0;
    private int offsetY = 100;
    private boolean hasPostRunnable = false;

    public ScrollTextView(Context context) {
        this(context, null);
    }

    public ScrollTextView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScrollTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        View view = LayoutInflater.from(context).inflate(R.layout.widget_scroll_text_layout, this);
        mBannerTV1 = view.findViewById(R.id.tv_banner1);
        mBannerTV2 = view.findViewById(R.id.tv_banner2);
        handler = new Handler();
        runnable = new Runnable() {
            @Override
            public void run() {
                isShow = !isShow;
                if (position == list.size() - 1) {
                    position = 0;
                }

                if (isShow) {
                    mBannerTV1.setText(list.get(position++));
                    mBannerTV2.setText(list.get(position));
                } else {
                    mBannerTV2.setText(list.get(position++));
                    mBannerTV1.setText(list.get(position));
                }

                startY1 = isShow ? 0 : offsetY;
                endY1 = isShow ? -offsetY : 0;
                ObjectAnimator.ofFloat(mBannerTV1, "translationY", startY1, endY1).setDuration(300).start();

                startY2 = isShow ? offsetY : 0;
                endY2 = isShow ? 0 : -offsetY;
                ObjectAnimator.ofFloat(mBannerTV2, "translationY", startY2, endY2).setDuration(300).start();

                handler.postDelayed(runnable, 3000);
            }
        };
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;

        //处理最后一条数据切换到第一条数据 太快的问题
        if (list.size() > 1) {
            list.add(list.get(0));
        }
    }

    public void startScroll() {
        mBannerTV1.setText(list.get(0));
        if (list.size() > 1) {
            if(!hasPostRunnable) {
                hasPostRunnable = true;
                //处理第一次进入 第一条数据切换第二条 太快的问题
                handler.postDelayed(runnable,3000);
            }
        } else {
            //只有一条数据不进行滚动
            hasPostRunnable = false;
//            mBannerTV1.setText(list.get(0));
        }
    }

    public void stopScroll() {
        handler.removeCallbacks(runnable);
        hasPostRunnable = false;
    }


}

Puntos a tener en cuenta: 1. Para activar y desactivar el desplazamiento, ambos deben controlarse fuera del control. Si necesita controlarlo usted mismo dentro del control,

onAttachedToWindow Inicie el hilo aquí, preste atención para determinar si la lista está vacía.

2. Cuando los datos de la lista sean mayores que 1, agregaré manualmente los primeros datos en la parte posterior. Para evitarlo, el último se cambia a uno porque el desplazamiento es demasiado rápido (es decir, el problema del efecto dinámico no obvio ), No lo juzgué aquí., Porque debe haber datos pasados, para que Yan Jin pueda agregar un espacio en blanco.


2.widget_scroll_text_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_banner1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:ellipsize="end"
        android:singleLine="true"
        android:textColor="@color/skin_common_title"
        android:textSize="12sp" />

    <TextView
        android:id="@+id/tv_banner2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:ellipsize="end"
        android:singleLine="true"
        android:textColor="@color/skin_common_title"
        android:textSize="12sp" />

</RelativeLayout>

3. Convocatoria específica

        ScrollTextView marqueeText = headView.findViewById(R.id.xxxx);

        List<String> demographicsList = new ArrayList<>();

        demographicsList.add("今日测试股票 上市");
        demographicsList.add("今日科伦药业 中国人保 可申购");
        demographicsList.add("今日中国平安 上市");

        marqueeText.setList(demographicsList);
        marqueeText.startScroll();

Nota: Maneje correctamente el problema del ciclo de vida.Cuando llamar a starScroll () y stopScroll (), depende del ciclo de vida específico;


cola:

Siento que puede definir cualquier animación que desee de esta manera, y puede personalizar la animación de atributos de acuerdo con sus necesidades, y no hay necesidad de un TextView () nuevo adicional; una mirada simple, parece que TextSwitch es un poco más molesto.

Una vez finalizada la tarea de hoy, estudiaré TextSwitch y compararé las ventajas y desventajas de los dos;

 

Supongo que te gusta

Origin blog.csdn.net/android_freshman/article/details/84105637
Recomendado
Clasificación