RecyclerView实现广告轮播图

来源:互联网 发布:淘宝神笔宝贝详情编辑 编辑:程序博客网 时间:2024/05/16 15:47

之前做的轮播图,对于十几个图片什么的能够满足,但是万一有几千张,几万张就容易造成内存泄露,使用RecyclerView做的轮播,可以利用它自身的复用机制,比较节省内存。所以这种方式感觉效果更好。
准备:build.gradle添加
compile ‘com.github.bumptech.glide:glide:3.7.0’
AndroidManifest.xml添加权限

效果图
这里写图片描述

public class RecyclerViewBanner extends FrameLayout {    private RecyclerView recyclerView;    private LinearLayout linearLayout;    private GradientDrawable defaultDrawable, selectedDrawable;    private ReyclerAdapter adapter;    private OnRvBannerClickListener onRvBannerClickListener;    private OnSwitchRvBannerListener onSwitchRvBannerListener;    /**     * 页面数据     */    private List datas = new ArrayList<>();    private int point_size, startX, startY, currentIndex;    /**     * 点的间隔     */    private int point_padding_left,point_padding_top,point_padding_right,point_padding_bottom;    /**     * 设置是否自动播放     */    private boolean isPlaying;    /**     * 页面停留时间     */    private int millisecond = 3000;    /**     * 是否显示底部导航点     */    private boolean isShowPoint = true;    /**     * 底部导航点的选中和未选中的颜色     */    private int pointFocusBg, pointUnFocusBg;    private Handler handler = new Handler();    /**     * 延时切换页面计时器     */    private Runnable playTask = new Runnable() {        @Override        public void run() {            recyclerView.smoothScrollToPosition(++currentIndex);            if (isShowPoint) {                switchIndicatorPoint();            }            handler.postDelayed(this, millisecond);        }    };    public RecyclerViewBanner(Context context) {        this(context, null);    }    public RecyclerViewBanner(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public RecyclerViewBanner(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);//        size = (int) (5 * context.getResources().getDisplayMetrics().density + 0.5f);//dp2px默认5dp        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecyclerViewBanner);        isShowPoint = typedArray.getBoolean(R.styleable.RecyclerViewBanner_isShowPoint, true);        pointFocusBg = typedArray.getColor(R.styleable.RecyclerViewBanner_pointFocusBg, 0xff0099ff);        pointUnFocusBg = typedArray.getColor(R.styleable.RecyclerViewBanner_pointUnfocusBg, 0xffffffff);        millisecond = typedArray.getInt(R.styleable.RecyclerViewBanner_interval, 3000);        point_size = typedArray.getInt(R.styleable.RecyclerViewBanner_point_size, (int) (5 * context.getResources().getDisplayMetrics().density + 0.5f));        point_padding_left = typedArray.getInt(R.styleable.RecyclerViewBanner_point_padding_left, point_size*2);        point_padding_top = typedArray.getInt(R.styleable.RecyclerViewBanner_point_padding_top, point_size*2);        point_padding_right = typedArray.getInt(R.styleable.RecyclerViewBanner_point_padding_right, point_size*2);        point_padding_bottom = typedArray.getInt(R.styleable.RecyclerViewBanner_point_padding_bottom, point_size*2);        typedArray.recycle();        recyclerView = new RecyclerView(context);        LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);        linearLayout = new LinearLayout(context);        linearLayout.setOrientation(LinearLayout.HORIZONTAL);        LayoutParams linearLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);        linearLayout.setGravity(Gravity.CENTER);        linearLayout.setPadding(point_padding_left, point_padding_top, point_padding_right, point_padding_bottom);        linearLayoutParams.gravity = Gravity.BOTTOM;        addView(recyclerView, vpLayoutParams);        addView(linearLayout, linearLayoutParams);        defaultDrawable = new GradientDrawable();        defaultDrawable.setSize(point_size, point_size);        defaultDrawable.setCornerRadius(point_size);        defaultDrawable.setColor(pointUnFocusBg);        selectedDrawable = new GradientDrawable();        selectedDrawable.setSize(point_size, point_size);        selectedDrawable.setCornerRadius(point_size);        selectedDrawable.setColor(pointFocusBg);        new PagerSnapHelper().attachToRecyclerView(recyclerView);        recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));        adapter = new ReyclerAdapter();        recyclerView.setAdapter(adapter);        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                int first = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();                int last = ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition();                if (currentIndex != (first + last) / 2) {                    currentIndex = (first + last) / 2;                    if (isShowPoint) {                        switchIndicatorPoint();                    }                }            }        });    }    public void setPoint_size(int point_size) {        this.point_size = point_size;    }    public void setPoint_padding_left(int point_padding_left) {        this.point_padding_left = point_padding_left;    }    public void setPoint_padding_top(int point_padding_top) {        this.point_padding_top = point_padding_top;    }    public void setPoint_padding_right(int point_padding_right) {        this.point_padding_right = point_padding_right;    }    public void setPoint_padding_bottom(int point_padding_bottom) {        this.point_padding_bottom = point_padding_bottom;    }    /**     * 设置是否显示指示器导航点     *     * @param flag     */    public void isShowIndicatorPoint(boolean flag) {        this.isShowPoint = flag;    }    /**     * 设置轮播间隔时间     *     * @param millisecond     */    public void setScrollIntervalTime(int millisecond) {        this.millisecond = millisecond;    }    /**     * 设置 是否自动播放(上锁)     *     * @param playing     */    public synchronized void setPlaying(boolean playing) {        if (!isPlaying && playing && adapter != null && adapter.getItemCount() > 2) {            handler.postDelayed(playTask, millisecond);            isPlaying = true;        } else if (isPlaying && !playing) {            handler.removeCallbacksAndMessages(null);            isPlaying = false;        }    }    /**     * 设置轮播数据集     *     * @param datas     */    public void setRvBannerDatas(List datas) {        setPlaying(false);        this.datas.clear();        linearLayout.removeAllViews();        if (datas != null) {            this.datas.addAll(datas);        }        if (this.datas.size() > 1) {            currentIndex = this.datas.size();            adapter.notifyDataSetChanged();            recyclerView.scrollToPosition(currentIndex);            if (isShowPoint) {                for (int i = 0; i < this.datas.size(); i++) {                    ImageView img = new ImageView(getContext());                    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);                    lp.leftMargin = point_size / 2;                    lp.rightMargin = point_size / 2;                    img.setImageDrawable(i == 0 ? selectedDrawable : defaultDrawable);                    linearLayout.addView(img, lp);                }            }            setPlaying(true);        } else {            currentIndex = 0;            adapter.notifyDataSetChanged();        }    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        //手动触摸的时候,停止自动播放,根据手势变换        switch (ev.getAction()) {            case MotionEvent.ACTION_DOWN:                startX = (int) ev.getX();                startY = (int) ev.getY();                getParent().requestDisallowInterceptTouchEvent(true);                setPlaying(false);                break;            case MotionEvent.ACTION_MOVE:                int moveX = (int) ev.getX();                int moveY = (int) ev.getY();                int disX = moveX - startX;                int disY = moveY - startY;                getParent().requestDisallowInterceptTouchEvent(2 * Math.abs(disX) > Math.abs(disY));                setPlaying(false);                break;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                setPlaying(true);                break;        }        return super.dispatchTouchEvent(ev);    }    @Override    protected void onAttachedToWindow() {        super.onAttachedToWindow();        setPlaying(true);    }    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        setPlaying(false);    }    @Override    protected void onWindowVisibilityChanged(int visibility) {        if (visibility == GONE) {            // 停止轮播            setPlaying(false);        } else if (visibility == VISIBLE) {            // 开始轮播            setPlaying(true);        }        super.onWindowVisibilityChanged(visibility);    }    /**     * recyclerview的adapter,适配器     */    private class ReyclerAdapter extends RecyclerView.Adapter {        @Override        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {            ImageView img = new ImageView(parent.getContext());            RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);            img.setScaleType(ImageView.ScaleType.CENTER_CROP);            img.setLayoutParams(params);            img.setId(R.id.icon);            img.setOnClickListener(new OnClickListener() {                @Override                public void onClick(View v) {                    if (onRvBannerClickListener != null) {                        onRvBannerClickListener.onClick(currentIndex % datas.size());                    }                }            });            return new RecyclerView.ViewHolder(img) {            };        }        @Override        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {            ImageView img = (ImageView) holder.itemView.findViewById(R.id.icon);            onSwitchRvBannerListener.switchBanner(position, img);        }        @Override        public int getItemCount() {            return datas == null ? 0 : datas.size() < 2 ? datas.size() : Integer.MAX_VALUE;        }    }    private class PagerSnapHelper extends LinearSnapHelper {        @Override        public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {            int targetPos = super.findTargetSnapPosition(layoutManager, velocityX, velocityY);            final View currentView = findSnapView(layoutManager);            if (targetPos != RecyclerView.NO_POSITION && currentView != null) {                int currentPostion = layoutManager.getPosition(currentView);                int first = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();                int last = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();                currentPostion = targetPos < currentPostion ? last : (targetPos > currentPostion ? first : currentPostion);                targetPos = targetPos < currentPostion ? currentPostion - 1 : (targetPos > currentPostion ? currentPostion + 1 : currentPostion);            }            return targetPos;        }    }    /**     * 改变导航的指示点     */    private void switchIndicatorPoint() {        if (linearLayout != null && linearLayout.getChildCount() > 0) {            for (int i = 0; i < linearLayout.getChildCount(); i++) {                ((ImageView) linearLayout.getChildAt(i)).setImageDrawable(i == currentIndex % datas.size() ? selectedDrawable : defaultDrawable);            }        }    }    /**     * 滑动切换监听接口     */    public interface OnSwitchRvBannerListener {        void switchBanner(int position, ImageView bannerView);    }    public void setOnSwitchRvBannerListener(OnSwitchRvBannerListener listener) {        this.onSwitchRvBannerListener = listener;    }    /**     * 点击监听接口     */    public interface OnRvBannerClickListener {        void onClick(int position);    }    public void setOnRvBannerClickListener(OnRvBannerClickListener onRvBannerClickListener) {        this.onRvBannerClickListener = onRvBannerClickListener;    }}

attr.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="RecyclerViewBanner">        <attr name="pointFocusBg" format="color" />        <attr name="pointUnfocusBg" format="color" />        <attr name="interval" format="integer" />        <attr name="point_padding_left" format="integer" />        <attr name="point_padding_top" format="integer" />        <attr name="point_padding_right" format="integer" />        <attr name="point_padding_bottom" format="integer" />        <attr name="point_size" format="integer" />        <attr name="isShowPoint" format="boolean" />    </declare-styleable></resources>

用法:
布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    xmlns:app="http://schemas.android.com/apk/res-auto"    tools:context="com.eno.fragment.home.FragmentMainHome">    <!-- TODO: Update blank fragment layout -->    <com.eno.widget.RecyclerViewBanner        android:id="@+id/rv_banner"        android:layout_width="match_parent"        android:layout_height="150dp"        app:interval="3000"        app:isShowPoint="true"        />    <TextView        android:id="@+id/tv_content"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:gravity="center"        android:text="@string/home" /></FrameLayout>

代码

public class FragmentMainHome extends BaseFragment {    @BindView(R.id.rv_banner)    RecyclerViewBanner recyclerViewBanner;    @BindView(R.id.tv_content)    TextView tvContent;    public static FragmentMainHome newInstance() {        FragmentMainHome f = new FragmentMainHome();        return f;    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.fragment_main_home, container, false);        ButterKnife.bind(this, view);        final List<Banner> banners = new ArrayList<>();        for (int i = 0; i < 2; i++) {            banners.add(new Banner("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1487221110004&di=d6043e4b0c90ddf3ea5096c3d8eb8f58&imgtype=0&src=http%3A%2F%2Fimage.tianjimedia.com%2FuploadImages%2F2014%2F067%2F5116EPAUD762_1000x500.jpg"));            banners.add(new Banner("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1487221129421&di=c085432cf7c15836f8a6479138740f39&imgtype=0&src=http%3A%2F%2Fimage85.360doc.com%2FDownloadImg%2F2015%2F05%2F0517%2F53199602_2.jpg"));            banners.add(new Banner("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1487221161254&di=fbb99c5dad3d5a2a2c8b0b44e8c0e081&imgtype=0&src=http%3A%2F%2Fimage.tianjimedia.com%2FuploadImages%2F2013%2F255%2FP52AOTE73EIG_1000x500.jpg"));        }        recyclerViewBanner.isShowIndicatorPoint(true);        recyclerViewBanner.setRvBannerDatas(banners);        recyclerViewBanner.setOnSwitchRvBannerListener(new RecyclerViewBanner.OnSwitchRvBannerListener() {            @Override            public void switchBanner(int position, ImageView bannerView) {                Glide.with(bannerView.getContext()).load(banners.get(position % banners.size()).getUrl()).placeholder(R.mipmap.ic_launcher).into(bannerView);            }        });        return view;    }    @Override    public void fetchData() {        /**在这里请求网络 */    }    private class Banner {        String url;        public Banner(String url) {            this.url = url;        }        public String getUrl() {            return url;        }    }}

属性说明:
pointFocusBg 设置底部导航小圆点的选中状态颜色
pointUnfocusBg 设置底部导航小圆点的未选中状态颜色
interval 设置轮播图滚动间隔时间
isShowPoint 设置是否显示底部指示导航小圆点
point_size设置导航点的大小
point_padding_left设置点的左内间距
point_padding_right设置点的右内间距
point_padding_bottom设置点的下内间距
point_padding_top设置点的上内间距

0 0
原创粉丝点击