Android仿制淘宝滚动图文条

作者: 一个有故事的程序员 | 来源:发表于2018-08-17 19:05 被阅读64次

    开篇废话

    产品让我们将“我的”页面改版,上面加了一个广告条,非常类似淘宝“我的”页面的广告条,然后就自己写了一个,虽然网上类似的教程有很多了,但是我用的这个实现方法我没有见过,如果大家有更好的办法请留言给我,谢谢。这里只提供一种思路,有兴趣的小伙伴可以自行封装一下,记得告知我。滚动图文条之GitHub地址,帮我点个Star。

    滚动图文条

    大概效果就是下图这样。

    滚动图文条

    思路

    1. 写一个不可用手滑动的RecyclerView
    2. 使用Handler定时RecyclerView自动滑动到下一个Item
    3. 使用smoothScrollToPosition使其平滑地滑动

    开始工作

    做一些基本工作

    写一个AdModel类。

    public class AdModel {
    
        public String title;
        public String content;
    
        public AdModel(String title, String content) {
            this.title = title;
            this.content = content;
        }
    }
    

    写一些item_ad布局。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:minHeight="50dp"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:background="@null"
        tools:background="@color/black">
    
        <LinearLayout
            android:id="@+id/ll_ad"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:orientation="vertical">
    
            <TextView
                android:id="@+id/tv_title"
                tools:text="会员身份0元抢"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:textColor="@color/white"
                android:textSize="12sp" />
    
            <TextView
                android:id="@+id/tv_content"
                tools:text="送你体验会员"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:textColor="@color/white"
                android:textSize="10sp" />
    
        </LinearLayout>
    
        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1"/>
    
        <ImageView
            android:id="@+id/iv_icon"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginRight="15dp"
            android:src="@drawable/icon"/>
    
    </LinearLayout>
    

    写AdAdapter类。

    public class AdAdapter extends RecyclerView.Adapter<AdAdapter.ViewHolder> {
    
        private Context mContext;
        private OnItemClickListener onItemClickListener;
        private LayoutInflater mInflater;
        private List<AdModel> mDataList;
    
        public AdAdapter(Context context, List<AdModel> datas) {
            this.mContext = context;
            mDataList = datas;
            mInflater = LayoutInflater.from(context);
        }
    
        @Override
        public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
            View itemView = mInflater.inflate(R.layout.item_ad, null);
            return new ViewHolder(itemView);
        }
    
        @Override
        public void onBindViewHolder(ViewHolder holder, final int p) {
            if (mDataList == null || mDataList.size() ==0){
                return;
            }
            if (holder != null) {
                final int position = p % mDataList.size();
    
                holder.mTvTitle.setText(mDataList.get(position).title);
                holder.mTvContent.setText(mDataList.get(position).content);
                holder.mIvIcon.setImageResource(R.drawable.icon);
    
                holder.viewRoot.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (onItemClickListener != null) {
                            onItemClickListener.onItemClick(v, position);
                        }
                    }
                });
            }
        }
    
        public void setOnItemClickListener(OnItemClickListener clickListener) {
            this.onItemClickListener = clickListener;
        }
    
        @Override
        public int getItemCount() {
            return mDataList == null ? 0 : Integer.MAX_VALUE;
        }
    
        public class ViewHolder extends RecyclerView.ViewHolder {
    
            public View viewRoot;
            public TextView mTvTitle;
            public TextView mTvContent;
            public ImageView mIvIcon;
    
            public ViewHolder(View itemView) {
                super(itemView);
                viewRoot = itemView.findViewById(R.id.layout);
                mTvTitle = itemView.findViewById(R.id.tv_title);
                mTvContent = itemView.findViewById(R.id.tv_content);
                mIvIcon = itemView.findViewById(R.id.iv_icon);
            }
        }
    
        /**
         * RecyclerView的item点击监听接口
         */
        public interface OnItemClickListener {
            void onItemClick(View v, int position);
        }
    
    }
    

    页面activity_main布局。

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.cc.scrolladbar.MainActivity">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_ad"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:layout_marginEnd="20dp"
            android:layout_marginStart="20dp"
            android:layout_marginTop="60dp"
            android:nestedScrollingEnabled="false"
            android:background="@color/black"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </android.support.constraint.ConstraintLayout>
    
    重点代码

    在MainActivity中写如下代码。

    package com.cc.scrolladbar;
    
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.LinearSmoothScroller;
    import android.support.v7.widget.RecyclerView;
    import android.util.DisplayMetrics;
    import android.view.View;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by guoshichao on 2018/8/16
     * QQ:1169380200
     */
    
    public class MainActivity extends AppCompatActivity {
    
        private static final int SCROLL_AD = 0;//会员轮播广告
        public static final int DEFAULT_SCROLL_INTERVAL = 3000;//会员轮播广告间隔时间
        public static final int DEFAULT_SCROLL_ANIMATION_TIME = 500;//会员轮播广告动画时长
    
        private RecyclerView mRvAd;
        private AdAdapter mAdapter;
        private List<AdModel> mAdList;
        private AdHandler mHandler;
        private int nowScrollPosition = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initList();
        }
    
        @Override
        public void onStart() {
            super.onStart();
            scrollVipAdOnce(nowScrollPosition);//防止滑动一半切到别的页面使滑动完成
            if (mHandler != null) {
                sendScrollMessage(DEFAULT_SCROLL_INTERVAL);
            }
        }
    
        @Override
        public void onStop() {
            super.onStop();
            if (mHandler != null) {
                mHandler.removeMessages(SCROLL_AD);
            }
        }
    
        private void initList() {
            mAdList = new ArrayList<>();
            mAdList.add(new AdModel("第一条广告标题", "我是第一条广告的内容哦~"));
            mAdList.add(new AdModel("第二条广告标题", "我是第二条广告的内容哦~"));
            mAdList.add(new AdModel("第三条广告标题", "我是第三条广告的内容哦~"));
    
            LinearLayoutManager manager = new LinearLayoutManager(this) {
                @Override
                public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
                    LinearSmoothScroller smoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
                        // 为了平滑滑动返回:滑过1px时经历的时间(ms)。
                        @Override
                        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                            return (float) (DEFAULT_SCROLL_ANIMATION_TIME / displayMetrics.densityDpi);
                        }
                    };
                    smoothScroller.setTargetPosition(position);
                    startSmoothScroll(smoothScroller);
                }
            };
    
            mRvAd = (RecyclerView) findViewById(R.id.rv_ad);
            mRvAd.setLayoutManager(manager);
            mAdapter = new AdAdapter(this, mAdList);
            mRvAd.setAdapter(mAdapter);
            mAdapter.setOnItemClickListener(new AdAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(View v, int position) {
                    //点击跳转到指定广告页
                }
            });
            mHandler = new AdHandler();
            sendScrollMessage(DEFAULT_SCROLL_INTERVAL);
        }
    
        private void scrollVipAdOnce(int position) {
            if (mAdList != null && mAdList.size() > 1) {
                //平滑滑动到指定位置
                mRvAd.smoothScrollToPosition(position);
            }
        }
    
        private void sendScrollMessage(long delayMillis) {
            mHandler.removeMessages(SCROLL_AD);
            mHandler.sendEmptyMessageDelayed(SCROLL_AD, delayMillis);
        }
    
        private class AdHandler extends Handler {
    
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
    
                switch (msg.what) {
                    case SCROLL_AD:
                        nowScrollPosition++;
                        scrollVipAdOnce(nowScrollPosition);
                        sendScrollMessage(DEFAULT_SCROLL_INTERVAL);
                        break;
                    default:
                        break;
                }
            }
        }
    
    }
    
    重点分析

    其中有一段代码比较重要。

    LinearLayoutManager manager = new LinearLayoutManager(this) {
                @Override
                public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
                    LinearSmoothScroller smoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
                        // 为了平滑滑动返回:滑过1px时经历的时间(ms)。
                        @Override
                        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
                            return (float) (DEFAULT_SCROLL_ANIMATION_TIME / displayMetrics.densityDpi);
                        }
                    };
                    smoothScroller.setTargetPosition(position);
                    startSmoothScroll(smoothScroller);
                }
            };
    

    这里是为了平滑滑动。因为距离比较短小或者别的原因,mRvAd.smoothScrollToPosition(position)无法使其平滑地滑动。故加以上代码。

    我的完成图如下。

    滚动图文条

    写在后面

    这个Demo比较简单,没什么技术难点,如果还是有些不懂的,可以留言,我在文中可以做更多的解释。如果有大佬有更好的解决方案,望指教。

    更多内容戳这里(整理好的各种文集)

    相关文章

      网友评论

      • 世道无情:大佬,请教下,如何在提交订单页面 显示购物车中选中的多个店铺和店铺下对应的商品呢
        世道无情:请教下,对于一个店铺下边有多个商品,如果我只选择1个或者2个商品,这个时候店铺复选框是没有选中的,那么怎样可以在提交订单页面知道选中这1个或者2个商品对应的店铺名称呢
        世道无情:@一个有故事的程序员 你好,我可以获取到选中的店铺list集合和选中的商品list集合,传递到提交订单页面,但是对于一个店铺下边有多个商品的话,如果我只选中商品,没有选中店铺,那么传递过去店铺的集合就不太对,商品的集合是对的,请问下这种情况怎么处理呢,我用ExpandListView做的
        一个有故事的程序员:@世道无情 传参数过去

      本文标题:Android仿制淘宝滚动图文条

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