Android自定义View——榜单自动滚动

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

Android动画实现一般都用animation
动画包含三大类型View Animation
帧动画(Drawable Animation)
Property Animation(属性动画); 属性动画比较好用,可以重点关注一下。
既然是滚动肯定要按国际滚动标准——向上平移啦!

实现原理

利用平移动画translate完成动画向上平移

在res—下新建文件夹anim(animation的简称) image.png

创建动画文件

anim_marquee_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="500"
        android:fromYDelta="100%p"
        android:toYDelta="0"/>
    <alpha
        android:duration="500"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>
</set>
复制代码

anim_marquee_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="500"
        android:fromYDelta="0"
        android:toYDelta="-100%p"/>
    <alpha
        android:duration="500"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"/>
</set>
复制代码

动画文件写好了就开始自定义view啦

首先来了解一下ViewFlipper

ViewFlipper是Android自带的一个多页面管理控件,且可以自动播放! 和ViewPager不同,ViewPager是一页页的,而ViewFlipper则是一层层的,和ViewPager一样,很多时候, 用来实现进入应用后的引导页,或者用于图片轮播。

android:inAnimation    //设置View或ImageView进入屏幕时使用的动画
android:outAnimation   //设置View或ImageView退出屏幕时使用的动画
android:flipInterval   //设置View或ImageView之间切换的时间间隔
复制代码

常用方法:

setInAnimation:设置View或ImageView进入屏幕时使用的动画
setOutAnimation:设置View或ImageView退出屏幕时使用的动画
showNext:调用该方法来显示ViewFlipper里的下一个View或ImageView
showPrevious:调用该方法来显示ViewFlipper的上一个View或ImageView
setFilpInterval:设置View或ImageView之间切换的时间间隔
startFlipping:使用上面设置的时间间隔来开始切换所有的View或ImageView,切换会循环进行
stopFlipping:停止View或ImageView切换
复制代码

我们重写ViewFlipper

public class UPMarqueeView extends ViewFlipper
复制代码

完整代码

代码里面有注释

/**
 * Created by JIULANG
 */
public class UPMarqueeView extends ViewFlipper {
    private Context mContext;
    private boolean isSetAnimDuration = false;
    private int interval = 3000;//间隔时间
    /**
     * 动画时间
     */
    private int animDuration = 500;

    public UPMarqueeView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        this.mContext = context;
        setFlipInterval(interval);
        Animation animIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_marquee_in);
        if (isSetAnimDuration) animIn.setDuration(animDuration);
        setInAnimation(animIn);
        Animation animOut = AnimationUtils.loadAnimation(mContext, R.anim.anim_marquee_out);
        if (isSetAnimDuration) animOut.setDuration(animDuration);
        setOutAnimation(animOut);
    }


    /**
     * 设置循环滚动的View数组
     *
     * @param views
     */
    public void setViews(final List<View> views) {
        if (views == null || views.size() == 0) return;
        removeAllViews();
        //遍历所有条目
        for ( int i = 0; i < views.size(); i++) {
            final int position=i;
            //设置监听回调
            views.get(i).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                //绑定点击事件
                    if (onItemClickListener != null) {
                        onItemClickListener.onItemClick(position, views.get(position));
                    }
                }
            });
            ViewGroup viewGroup = (ViewGroup) views.get(i).getParent();
            if (viewGroup != null) {
                viewGroup.removeAllViews();
            }
            addView(views.get(i));
        }
        startFlipping();
    }

    /**
     * 点击
     */
    private OnItemClickListener onItemClickListener;

    /**
     * 设置监听接口
     * @param onItemClickListener
     */
    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    /**
     * item_view的接口
     */
    public interface OnItemClickListener {
        void onItemClick(int position, View view);
    }
}
复制代码

条目的布局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:padding="8dp">

    <ImageView
        android:id="@+id/iv_cup"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:src="@drawable/ic_vip5"
        android:paddingTop="9dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>


    <TextView
        android:id="@+id/name_type"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/black"
        android:textSize="16sp"
        android:textStyle="bold"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/iv_cup"/>

    <TextView
        android:id="@+id/rank_type"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:layout_marginLeft="16dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/name_type"/>

    <TextView
        android:id="@+id/no_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="hi"
        android:textColor="@color/black"
        android:textSize="14sp"
        android:visibility="gone"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>


    <ImageView
        android:id="@+id/iv_portrait"
        android:layout_width="26dp"
        android:layout_height="26dp"
        android:src="@drawable/ic_my"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
复制代码

使用方法

List<View> mViewList = new ArrayList<>();
UPMarqueeView mUPMarqueeView = findViewById(R.id.upMarqueeView);

//模拟加载数据
for (int i = 0; i < 9; i++) {
    final View rankView = LayoutInflater.from(this).inflate(R.layout.view_main_rank, mUPMarqueeView, false);
    TextView nameType = rankView.findViewById(R.id.name_type);
    nameType.setText("九狼");
    TextView rankType = rankView.findViewById(R.id.rank_type);
    rankType.setText("点个赞吧!");
    mViewList.add(rankView);
}
mUPMarqueeView.setViews(mViewList);
复制代码

效果图

ezgif.com-gif-maker (3).gif

Guess you like

Origin juejin.im/post/7033794377239494664