美文网首页app开发andnroid自定义
京东快报轮播公告的实现

京东快报轮播公告的实现

作者: xiaoyanger | 来源:发表于2017-01-14 23:50 被阅读2301次

    手机京东app首页的京东快报有一个无限轮播的公告栏,先看效果:


    京东快报轮播公告.gif

    公告内容大概每3s从中间向上滑出,同时下一条内容从底部向上滑动进入。整个过程还伴随有内容的渐变消失。
    开始想这样的效果可以通过自绘控件来实现,后面再想想采用ViewFlipper来实现更为简单。
    看看ViewFlipper类官方注释:

    Simple {@link ViewAnimator} that will animate between two or more views that have been added to it. Only one child is shown at a time. If requested, can automatically flip between each child at a regular interval.

    大概意思就是ViewFlipper是一个容器,能够将添加在里面的两个或更多子View动画的切换,在一个时间点只有一个child展示出来。并且可以自动的在每隔一个时间段切换到一个child。
    要实现京东快报的切换效果,我们只需要将需要根据轮播的公告内容设置到TextView并添加到ViewFlipper,同时设置他们之间的切换动画就可以了。

    为了方便在项目中直接使用,我们将其自定义为一个继承自ViewFlipper的控件NoticeView。

    /**
     * Created by xjj on 2017/1/14.
     * 轮播公告Veiw
     */
    public class NoticeView extends ViewFlipper implements View.OnClickListener {
    
        private Context mContext;
        private List<String> mNotices;
    
        public NoticeView(Context context) {
            super(context);
        }
    
        public NoticeView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        private void init(Context context) {
            mContext = context;
            // 轮播间隔时间为3s
            setFlipInterval(3000);
            // 内边距5dp
            setPadding(dp2px(5f), dp2px(5f), dp2px(5f), dp2px(5f));
            // 设置enter和leave动画
            setInAnimation(AnimationUtils.loadAnimation(mContext, R.anim.notify_in));
            setOutAnimation(AnimationUtils.loadAnimation(mContext, R.anim.notify_out));
        }
    
        /**
         * 添加需要轮播展示的公告
         *
         * @param notices
         */
        public void addNotice(List<String> notices) {
            mNotices = notices;
            removeAllViews();
            for (int i = 0; i < mNotices.size(); i++) {
                // 根据公告内容构建一个TextView
                String notice = notices.get(i);
                TextView textView = new TextView(mContext);
                textView.setSingleLine();
                textView.setText(notice);
                textView.setTextSize(13f);
                textView.setEllipsize(TextUtils.TruncateAt.END);
                textView.setTextColor(Color.parseColor("#666666"));
                textView.setGravity(Gravity.CENTER_VERTICAL);
                // 将公告的位置设置为textView的tag方便点击是回调给用户
                textView.setTag(i);
                textView.setOnClickListener(this);
                // 添加到ViewFlipper
                NoticeView.this.addView(textView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            }
        }
    
        @Override
        public void onClick(View v) {
            int position = (int) v.getTag();
            String notice = (String) mNotices.get(i);
            if (mOnNoticeClickListener != null) {
                mOnNoticeClickListener.onNotieClick(position, notice);
            }
        }
    
        /**
         * 通知点击监听接口
         */
        public interface OnNoticeClickListener {
            void onNotieClick(int position, String notice);
        }
    
        private OnNoticeClickListener mOnNoticeClickListener;
    
        /**
         * 设置通知点击监听器
         *
         * @param onNoticeClickListener 通知点击监听器
         */
        public void setOnNoticeClickListener(OnNoticeClickListener onNoticeClickListener) {
            mOnNoticeClickListener = onNoticeClickListener;
        }
    
        private int dp2px(float dpValue) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    dpValue,
                    mContext.getResources().getDisplayMetrics());
        }
    }
    

    公告内容进入动画notice_in.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <!--平移-->
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromYDelta="50%p"
            android:toYDelta="0"/>
        <!--渐变-->
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="0.0"
            android:toAlpha="1.0"/>
    </set>
    

    公告内容滑出动画notice_out.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <!--平移-->
        <translate
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromYDelta="0"
            android:toYDelta="-50%p"/>
        <!--渐变-->
        <alpha
            android:duration="@android:integer/config_mediumAnimTime"
            android:fromAlpha="1.0"
            android:toAlpha="0.0"/>
    </set>
    

    在Activity中使用

    private void init() {
        NoticeView noticeView = (NoticeView) findViewById(R.id.notice_view);
        List<String> notices = new ArrayList<>();
        notices.add("大促销下单拆福袋,亿万新年红包随便拿");
        notices.add("家电五折团,抢十亿无门槛现金红包");
        notices.add("星球大战剃须刀首发送200元代金券");
        noticeView.addNotice(notices);
        noticeView.startFlipping();
    }
    

    最终效果(布局代码就不贴了,比较简单)


    京东快报轮播公告最终实现效果图

    源码:https://github.com/xiaoyanger0825/NoticeView

    相关文章

      网友评论

      • 酒杯里的梦想:很多 app 现在都做了这个功能
      • 0青衣小褂0:楼主,我想监听退出动画监听不到,进入动画可以监听到,你有研究过这个问题吗
        xiaoyanger:@0青衣小褂0 怎么没用呢
        0青衣小褂0:设置outAnimation没有起作用
      • 路易十四_bc70:这真是巧合
      • 萨飞:谢谢分享. 提个建议可以 吧这一个效果, 集锦大家意见,做个封装
      • 1728fedc61c1:图片轮播是不是也可以用这种方式呢 ?
        1728fedc61c1:@xiaoyanger 看了您的博客 受益颇多。感谢
        xiaoyanger:@哗啦啦啦_ef96 当然可以的
      • 热血沸腾:这种实现不知道嵌入到有上拉刷新AbList的header里,有木有重叠的问题,实现确实简单许多,新的思路,谢了
        xiaoyanger:可以试一下呢,应该木有重叠问题的
      • b2be52039e20:还没设置点击监听吧
        xiaoyanger:@望梅不止渴 自定义NoticeView的代码里面实现了点击监听的逻辑,只是在使用的时候没监听
      • dc11426c6056:学习啦
      • 蜉杰辰蝣:楼主棒棒哒😊
        xiaoyanger: @蜉杰辰蝣 谢谢😆
      • becc81d39cc5:Viewflipper 更简单
        xiaoyanger: @无未 就是呢😆

      本文标题:京东快报轮播公告的实现

      本文链接:https://www.haomeiwen.com/subject/okyebttx.html