自定义view:信息飘窗/弹幕——AutoSwitchTextView

13 篇文章 2 订阅
13 篇文章 5 订阅

一、实现背景

项目中,闪购页面 用于自动切换 展示 购买信息,就是那种 “xxx 10s 买了huawei p30 ” 然后自动翻滚上去,接着底部向上滑出下一条。效果如下图。(感觉有点像连续多个Toast)    也可参考小红书的闪购页面~

即,从下面较快的出现,停留展示一会,在缓慢的向上滑出。

二、实现思路

一开始想的是,使用TextSwitcher实现,因为之前做过类似的文字切换。但效果给UI看后表示不行。因为要参考小红书的效果来,就去瞅了瞅。特点是 文字是一条一条的出现,而TextSwitcher是连着两个Text进行翻转。所以考虑自定义,使用属性动画来实现。 

!2天后来更新:上面用属性动画实现,在红米5表现ok;但是其他手机(荣耀、oppo)都不行,只有第一次效果ok,后面就闪过或者只出现两次 就没了。 试了很多次又查了资料,说 属性动画 是做不到循环的(原因不清楚),所以改为使用view动画

三、代码说明

1、方式一,属性动画(效果不佳,弃用了)

代码很简单,有注释。在代码中调用

//显示飘窗
mAutoSwitchTextView.setData(list); 

即可展示出来。


/**
 * @apiNote 自动向上翻滚的view,用于信息展示~
 * @author hufy
 * @date 2019/7/4 17:34
 */
public class AutoSwitchTextView extends RelativeLayout {

    /**
     * 展示的数据
     */
    private List<FlashBuyerInfo.Buyer> dataList = new ArrayList<>();

    /**
     * 用于翻滚的textView
     */
    private TextView mTextView;

    /**
     * index
     */
    private int index = 0;

    /**
     * 动画集合
     */
    private AnimatorSet mAnimatorSet;

    public AutoSwitchTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    private void initView(Context context) {
        mTextView = new TextView(context);
        mTextView.setTextColor(ResUtil.getColor(R.color.common_color_ffffff));
        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10);
        mTextView.setBackgroundResource(R.drawable.text_switch_bg);
        mTextView.setPadding(CommonUtils.dip2px(8), 0 ,CommonUtils.dip2px(8) ,0);
        mTextView.setGravity(Gravity.CENTER);
        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
        addView(mTextView, layoutParams);
    }

    /**
     * 设置要展示的数据,会自动开始翻滚。
     * @param dataList
     */
    public void setData(List<FlashBuyerInfo.Buyer> dataList){
        this.dataList = dataList;
        setVisibility(View.VISIBLE);
        start();
    }

    /**
     * 快速向上滑动text、停留展示、向上滑出、等待x 秒后 继续下一个text 。
     */
    private void start(){

        int size = dataList.size();
        index = 0;
        setTextInfo(index);

        mAnimatorSet = new AnimatorSet();

        //从底部出现
        ObjectAnimator showAnimator = ObjectAnimator.ofFloat(mTextView, "translationY", 100, 0);
        showAnimator.setDuration(500);

        //向上滑出
        ObjectAnimator outAnimator = ObjectAnimator.ofFloat(mTextView, "translationY", 0, -100);
        outAnimator.setDuration(1000);
        outAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                //动画结束后,继续下一个
                index++;
                if (index <= size - 1){
                    setTextInfo(index);
                    long nextPopupTime = getNextPopupTime(index);
                    mAnimatorSet.play(outAnimator).after(1500).after(showAnimator);
                    mAnimatorSet.setStartDelay(nextPopupTime);
                    mAnimatorSet.start();
                }
            }
        });

        mAnimatorSet.play(outAnimator).after(1500).after(showAnimator);
        mAnimatorSet.start();
    }

    /**
     * 结束动画
     */
    public void finish(){
        if (mAnimatorSet != null) {
            mAnimatorSet.end();
        }
    }

    /**
     * 获取 等待多久后 继续下一条弹窗
     * @param index
     * @return
     */
    private long getNextPopupTime(int index) {
        FlashBuyerInfo.Buyer buyer = dataList.get(index);
        return buyer.getNextPopupTime() * 1000;
    }


    /**
     *  设置文字、图片
     * @param index
     */
    private void setTextInfo(int index) {
        FlashBuyerInfo.Buyer buyer = dataList.get(index);
        String text = buyer.getText();
        mTextView.setText(text);
    }


}

xml中使用 很简单:

    <AutoSwitchTextView
        android:id="@+id/flash_sale_auto_switch_text"
        android:layout_marginTop="250dp"
        android:layout_marginLeft="@dimen/aku_margin_8"
        android:layout_width="wrap_content"
        android:layout_height="24dp"
        android:gravity="center"/>

方式二、view动画(最后采取的方式)

  就是写两个view动画,一个从底部出现到中间,结束后另一个从中间向上滑出(滑出的时机要延迟一会,用于信息的停留展示)。然后结束后修改信息内容,在次执行。



/**
 * @apiNote 自动向上翻滚的view,~
 * @author hufy
 * @date 2019/7/4 17:34
 */
public class AutoSwitchTextView extends RelativeLayout {

    /**
     * 展示的数据
     */
    private List<FlashBuyerInfo.Buyer> dataList = new ArrayList<>();

    /**
     * 用于翻滚的textView
     */
    private TextView mTextView;

    /**
     * index
     */
    private int index = 0;


    public AutoSwitchTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    private void initView(Context context) {
        mTextView = new TextView(context);
        mTextView.setTextColor(ResUtil.getColor(R.color.common_color_ffffff));
        mTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10);
        mTextView.setBackgroundResource(R.drawable.text_switch_bg);
        mTextView.setPadding(CommonUtils.dip2px(8), 0 ,CommonUtils.dip2px(8) ,0);
        mTextView.setGravity(Gravity.CENTER);
        LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
        addView(mTextView, layoutParams);
    }

    /**
     * 设置要展示的数据,会自动开始翻滚。
     * @param dataList
     */
    public void setData(List<FlashBuyerInfo.Buyer> dataList){
        this.dataList = dataList;
        setVisibility(View.VISIBLE);
        start();
    }

    /**
     * 快速向上滑动text、停留展示、向上滑出、等待x 秒后 继续下一个text 。
     */
    private void start(){

        int size = dataList.size();
        index = 0;
        setTextInfo(index);

        //1.从底部出现
        TranslateAnimation showAnimator = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
                Animation.RELATIVE_TO_PARENT, 1, Animation.ABSOLUTE, 0);
        showAnimator.setDuration(500);
        showAnimator.setFillAfter(true);

        //2、停留1.5s 向上滑出
        TranslateAnimation outAnimator = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF,
                0, Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_PARENT, -1);
        outAnimator.setDuration(1000);
        outAnimator.setFillAfter(true);
        outAnimator.setStartOffset(1500);

        showAnimator.setAnimationListener(new AnimationEndListener() {
            @Override
            void onAnimationFinish(Animation animation) {
                mTextView.startAnimation(outAnimator);
            }
        });

        outAnimator.setAnimationListener(new AnimationEndListener() {
            @Override
            void onAnimationFinish(Animation animation) {
                index++;
                if (index <= size - 1){
                    setTextInfo(index);
                    long nextPopupTime = getNextPopupTime(index);
                    showAnimator.setStartOffset(nextPopupTime);
                    mTextView.startAnimation(showAnimator);
                }
            }
        });

        mTextView.startAnimation(showAnimator);
    }

    /**
     * 结束动画
     */
    public void finish(){
        if (mTextView != null) {
            mTextView.clearAnimation();
        }
    }

    /**
     * 获取 等待多久后 继续下一条弹窗
     * @param index
     * @return
     */
    private long getNextPopupTime(int index) {
        FlashBuyerInfo.Buyer buyer = dataList.get(index);
        return buyer.getNextPopupTime() * 1000;
    }


    /**
     *  设置文字、图片
     * @param index
     */
    private void setTextInfo(int index) {
        FlashBuyerInfo.Buyer buyer = dataList.get(index);
        String text = buyer.getText();
        mTextView.setText(text);
    }

    abstract class AnimationEndListener implements Animation.AnimationListener{


        @Override
        public void onAnimationStart(Animation animation) {
            //nothing
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            onAnimationFinish(animation);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            //nothing
        }

        abstract void onAnimationFinish(Animation animation);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值