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
- RecyclerView实现广告轮播图
- RecyclerView实现广告轮播图(一)
- RecyclerView嵌套ViewPager实现淘宝搜狐主页广告轮播图
- 使用RecyclerView + ViewPager 实现轮播广告的两个Bug
- RecyclerView 实现轮播图
- Android广告轮播图实现
- Android广告轮播图效果实现
- iOS 广告轮播图的实现
- 简单的实现轮播图和RecyclerView效果
- 【Android UI】ViewFlipper实现广告轮播图
- 使用ViewPager实现广告轮播图效果
- iOS 广告轮播图的实现与封装
- Android开发之轮播图广告的实现
- RecyclerView实现Gallery
- 使用ViewGroup实现RecyclerView
- RecyclerView实现手风琴效果
- RecyclerView实现倒序列表
- RecyclerView下拉刷新实现
- cookie和session的区别?
- 广州“大都市”仍在超期服役,商户:希望政府早出详细规划
- Recyclerview--两行代码轻松添加点击选中效果
- poj 2886
- 图解快速排序
- RecyclerView实现广告轮播图
- ffmpeg
- 开博了
- Introduction to 3D Game Programming with DirectX 11学习笔记 5 渲染管线(一)
- 从例子中学习闭包和范式for
- fdghhhhhhhhhhhh
- 卷积
- [iBET Malaysia]Sports Book Rebate 0.35% Bonus
- 消息摘要加密算法MD