当前位置: 首页 > news >正文

【Android】ViewPager2实现手/自动轮播图

轮播图

轮播图的基本概念

定义:轮播图是一种可以水平或垂直滑动切换的多内容展示区域,通常自动循环播放。

实现

添加依赖

这里我们通过Glide加载图片,所以添加Glide的依赖

  implementation 'com.github.bumptech.glide:glide:4.16.0'
布局

这里viewpager2就是我们进行轮播的对象,LinearLayout是我们添加指示器的布局(用于显示当前是第几张图片的下标指示器);

<androidx.constraintlayout.widget.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:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><androidx.viewpager2.widget.ViewPager2android:id = "@+id/vp2_main"android:layout_width="match_parent"android:layout_height="400dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintStart_toStartOf="parent"></androidx.viewpager2.widget.ViewPager2><LinearLayoutandroid:orientation="horizontal"android:id = "@+id/ll_main"app:layout_constraintStart_toStartOf="@+id/vp2_main"app:layout_constraintBottom_toBottomOf="@+id/vp2_main"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintEnd_toEndOf="@+id/vp2_main"></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Viewpager2创建布局

这里很简单,就是一个 ImageView

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id = "@+id/iv_vp2"android:layout_width="match_parent"android:layout_height="match_parent"android:src="@drawable/newyifu"android:scaleType="centerCrop"></ImageView>
</androidx.constraintlayout.widget.ConstraintLayout>
Viewpager2适配器的创建

因为我们使用的是Glide加载图片,Gilde可以大大提高图片加载的性能,同时要异步操作;

Glide.with(context).load(list.get(position)).into(holder.imageView);

这里with需要context,我们在onCreateViewHolder方法中可以通过父布局来获得contextload方法代表我们加载的资源,into代表我们要加载到哪里;

其他部分没变化;

public class Viewpage2Adapter extends RecyclerView.Adapter<Viewpage2Adapter.viewhold> {List<Integer> list;Context context;public Viewpage2Adapter(List<Integer> list) {this.list = list;}@NonNull@Overridepublic viewhold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {context = parent.getContext();View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_vp2,parent,false);return new viewhold(view);}@Overridepublic void onBindViewHolder(@NonNull viewhold holder, int position) {//使用glide加载可以优化流程,gilde加载属于异步Glide.with(context).load(list.get(position)).into(holder.imageView);}@Overridepublic int getItemCount() {return list == null ? 0 : list.size();}class viewhold extends RecyclerView.ViewHolder{ImageView imageView;public viewhold(@NonNull View itemView) {super(itemView);imageView = itemView.findViewById(R.id.iv_vp2);}}
}
实现轮播效果

我们通过Carousel来实现轮播效果;

public class Carousel {private Context context;//得到contextprivate ViewPager2 mviewpage2;private LinearLayout mlinearLayout;//得到它用来设置指示器private List<ImageView> midtlist = new LinkedList<>();private List<Integer> midlist = new LinkedList<>();  //用于存放大图的Id,为了后续实现轮播效果private Long AUTO_SCROLL_INTERAEL = 1_500L;public Carousel(Context context, LinearLayout mlinearLayout, ViewPager2 mviewpage2) {this.context = context;this.mlinearLayout = mlinearLayout;this.mviewpage2 = mviewpage2;}public void init(List<Integer> idlist) {for (int i : idlist) {midlist.add(i);ImageView imageView = new ImageView(context);if (midlist.size()==1) {imageView.setImageResource(R.drawable.cheng);} else {imageView.setImageResource(R.drawable.grey);}LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(50, 50);layoutParams.setMargins(5, 0, 5, 0);imageView.setLayoutParams(layoutParams);midtlist.add(imageView);mlinearLayout.addView(imageView);}midlist.add(0, midlist.get(midlist.size()  - 1));midlist.add(midlist.get(1));Log.d("gk",""+midlist.get(0));Viewpage2Adapter viewpage2Adapter = new Viewpage2Adapter(midlist);mviewpage2.setAdapter(viewpage2Adapter);mviewpage2.setCurrentItem(1, false);//实现轮播mviewpage2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {for (int i1 = 0; i1 < midtlist.size(); i1++) {if (i1 == position - 1) {midtlist.get(i1).setImageResource(R.drawable.cheng);} else {midtlist.get(i1).setImageResource(R.drawable.grey);}}if (position == midlist.size() - 1) {mviewpage2.setCurrentItem(1, false);}if (position == 0) {mviewpage2.setCurrentItem(midlist.size() - 2, false);}super.onPageSelected(position);}});}};
}

我们来分解一下代码:

  private Context context;//得到contextprivate ViewPager2 mviewpage2;private LinearLayout mlinearLayout;//得到它用来设置指示器private List<ImageView> midtlist = new LinkedList<>();private List<Integer> midlist = new LinkedList<>();  //用于存放大图的Id,为了后续实现轮播效果private Long AUTO_SCROLL_INTERAEL = 1_500L;public Carousel(Context context, LinearLayout mlinearLayout, ViewPager2 mviewpage2) {this.context = context;this.mlinearLayout = mlinearLayout;this.mviewpage2 = mviewpage2;}

context是为了后面newImageView的对象;
mlinearLayout是为了设置指示器;
midtlist是为了后面更新指示器的操作;
因为轮播的图片会有变动,所以我们需要保存变动后的图片资源,记为midlistAUTO_SCROLL_INTERAEL是轮播的时间;

  for (int i : idlist) {midlist.add(i);             //把资源加到新的保存资源的List中;ImageView imageView = new ImageView(context);  //创建对应的指示器if (midlist.size()==1) {     //初始化,指向首位imageView.setImageResource(R.drawable.cheng);} else {imageView.setImageResource(R.drawable.grey);}LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(50, 50);   //设置这个指示的宽高layoutParams.setMargins(5, 0, 5, 0);   //设置指示器的边距imageView.setLayoutParams(layoutParams);   //绑定布局参数midtlist.add(imageView);        //添加到list中,方便后续更新mlinearLayout.addView(imageView);  //添加到布局中}

这段代码的作用是设置指示器(图片的下标);

        //把最后一张资源设置到第一张midlist.add(0, midlist.get(midlist.size()  - 1));//把第一张资源设置到最后一张midlist.add(midlist.get(1));Log.d("gk",""+midlist.get(0));Viewpage2Adapter viewpage2Adapter = new Viewpage2Adapter(midlist);mviewpage2.setAdapter(viewpage2Adapter);//初始化到轮播图的第一张;mviewpage2.setCurrentItem(1, false);

这段代码的作用是初始化;把增加midlist的页数就是为了轮播时的切换;比如轮播到最后一页时,滑到下一页就是第一页,这是我们也偷偷切换到真的第一张,就能避免生硬的切换,使得看起来的效果更逼真;

   mviewpage2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageSelected(int position) {for (int i1 = 0; i1 < midtlist.size(); i1++) {if (i1 == position - 1) {midtlist.get(i1).setImageResource(R.drawable.cheng);} else {midtlist.get(i1).setImageResource(R.drawable.grey);}}if (position == midlist.size() - 1) {mviewpage2.setCurrentItem(1, false);}if (position == 0) {mviewpage2.setCurrentItem(midlist.size() - 2, false);}super.onPageSelected(position);}});

这里的效果是手动轮播;我们自行观看代码理解就OK;
想解释的一点是:i1 == position - 1这个条件,因为我们的轮播的页面多了,但是指示器还是原来的;所以这里我们这样设置就能避免指示器更新混乱的问题了;
position == midlist.size() - 1就是当它是第一页的内容的时候,我们切换为实际第一页的内容,这样看起来就很比较丝滑不生硬;

自动轮播
    Handler handler = new Handler(Looper.getMainLooper());
//得到handler的对象private final Runnable anToScrollRunnable = new Runnable() {@Overridepublic void run() {int currentitem = mviewpage2.getCurrentItem();if (currentitem == midlist.size() - 2) {mviewpage2.setCurrentItem(1,false);} else {mviewpage2.setCurrentItem(currentitem + 1);}handler.postDelayed(anToScrollRunnable, AUTO_SCROLL_INTERAEL);}};

这段代码如果理解了手动的话,自动也不难理解;
然后我们在手势变换的回调中进行设置:

          @Overridepublic void onPageScrollStateChanged(int state) {if (state == ViewPager2.SCROLL_STATE_DRAGGING) {handler.removeCallbacks(anToScrollRunnable);} else if (state == ViewPager2.SCROLL_STATE_IDLE) {handler.removeCallbacks(anToScrollRunnable);handler.postDelayed(anToScrollRunnable, AUTO_SCROLL_INTERAEL);}super.onPageScrollStateChanged(state);}

handler.removeCallbacks(anToScrollRunnable);
就是在任务队列中,移除还没有开始执行的任务

handler.postDelayed(anToScrollRunnable, AUTO_SCROLL_INTERAEL);
就是延迟执行任务,第一个参数是任务,第二个参数是延迟的时间

那么为什么需要移除,因为你如果没有取消“预约”的任务,一直堆积,那么最后的效果可能是,1.5秒切3次等等;

handler.removeCallbacks(anToScrollRunnable);就是停止自动轮播

handler.postDelayed(anToScrollRunnable, AUTO_SCROLL_INTERAEL);就是开始自动轮播

大家可以根据自己的理解自己设置;

我实现的效果:

在这里插入图片描述

最后方便大家学习,贴上综合代码:

public class Carousel {private Context context;//得到contextprivate ViewPager2 mviewpage2;private LinearLayout mlinearLayout;//得到它用来设置指示器private List<ImageView> midtlist = new LinkedList<>();private List<Integer> midlist = new LinkedList<>();  //用于存放大图的Id,为了后续实现轮播效果private boolean AUTO_SCROLL = false;private Long AUTO_SCROLL_INTERAEL = 1_500L;Handler handler = new Handler(Looper.getMainLooper());public Carousel(Context context, LinearLayout mlinearLayout, ViewPager2 mviewpage2) {this.context = context;this.mlinearLayout = mlinearLayout;this.mviewpage2 = mviewpage2;}public void init(List<Integer> idlist) {for (int i : idlist) {midlist.add(i);ImageView imageView = new ImageView(context);if (midlist.size()==1) {imageView.setImageResource(R.drawable.cheng);} else {imageView.setImageResource(R.drawable.grey);}LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(50, 50);layoutParams.setMargins(5, 0, 5, 0);imageView.setLayoutParams(layoutParams);midtlist.add(imageView);mlinearLayout.addView(imageView);}midlist.add(0, midlist.get(midlist.size()  - 1));midlist.add(midlist.get(1));Log.d("gk",""+midlist.get(0));Viewpage2Adapter viewpage2Adapter = new Viewpage2Adapter(midlist);mviewpage2.setAdapter(viewpage2Adapter);mviewpage2.setCurrentItem(1, false);//实现轮播mviewpage2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {@Overridepublic void onPageScrollStateChanged(int state) {if (state == ViewPager2.SCROLL_STATE_DRAGGING) {handler.removeCallbacks(anToScrollRunnable);} else if (state == ViewPager2.SCROLL_STATE_IDLE) {handler.removeCallbacks(anToScrollRunnable);handler.postDelayed(anToScrollRunnable, AUTO_SCROLL_INTERAEL);}super.onPageScrollStateChanged(state);}@Overridepublic void onPageSelected(int position) {for (int i1 = 0; i1 < midtlist.size(); i1++) {if (i1 == position - 1) {midtlist.get(i1).setImageResource(R.drawable.cheng);} else {midtlist.get(i1).setImageResource(R.drawable.grey);}}if (position == midlist.size() - 1) {mviewpage2.setCurrentItem(1, false);}if (position == 0) {mviewpage2.setCurrentItem(midlist.size() - 2, false);}super.onPageSelected(position);}});}private final Runnable anToScrollRunnable = new Runnable() {@Overridepublic void run() {int currentitem = mviewpage2.getCurrentItem();if (currentitem == midlist.size() - 2) {mviewpage2.setCurrentItem(1,false);} else {mviewpage2.setCurrentItem(currentitem + 1);}handler.postDelayed(anToScrollRunnable, AUTO_SCROLL_INTERAEL);}};
}
public class Viewpage2Adapter extends RecyclerView.Adapter<Viewpage2Adapter.viewhold> {List<Integer> list;Context context;public Viewpage2Adapter(List<Integer> list) {this.list = list;}@NonNull@Overridepublic viewhold onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {context = parent.getContext();View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_vp2,parent,false);return new viewhold(view);}@Overridepublic void onBindViewHolder(@NonNull viewhold holder, int position) {//使用glide加载可以优化流程,gilde加载属于异步Glide.with(context).load(list.get(position)).into(holder.imageView);}@Overridepublic int getItemCount() {return list == null ? 0 : list.size();}class viewhold extends RecyclerView.ViewHolder{ImageView imageView;public viewhold(@NonNull View itemView) {super(itemView);imageView = itemView.findViewById(R.id.iv_vp2);}}
}
http://www.dtcms.com/a/532476.html

相关文章:

  • 产品营销网站可以做英语翻译兼职的网站
  • jQuery Mobile 图标:全面解析与应用指南
  • Java(File)
  • AI 翻译入门指南:机器如何理解语言
  • 怎样上传网站程序网站数据库怎么配置
  • MySQL相关知识查询表中的内容(第三次作业)
  • h5游戏免费下载:过马路小游戏
  • 昆山建设局网站深圳企业有限公司
  • LangGraph 官方教程:聊天机器人之三
  • Anaconda的常用指令
  • 广州白云区网站开发做网站的公司叫什么名字好
  • 大兴安岭网站建设兼职有哪些网站可以做ppt
  • dfs:选数
  • 2.2.1.3 大数据方法论与实践指南-文档管理规范
  • 【智能制造工厂工业资料集】流程制造智能工厂总体架构及建设路线规划方案(PPT)
  • MFC简单入门学习
  • HD 钱包- MetaMask
  • 米拓做的网站如何改代码互联网站备案登记表
  • 【Go】--抛出和处理异常
  • Word转PDF工具,免费生成图片型文档
  • [sam2图像分割] MemoryAttentionLayer._forward_ca | 交叉注意力
  • 孝感网站建设公司电子商务平台内经营者享有公平交易的权利
  • Go语言:常量计数器iota的意义
  • 27-Scikit Learn:讲解Python中经典的机器学习工具库
  • 做网站运营工作流程网络营销概念
  • nnUNetv2
  • Android Studio新手开发第三十二天
  • 《神领物流》day08-作业范围微服务_完整代码【简单易懂注释版】
  • 西安网站定制开发h5课件制作软件
  • ABAP 调用接口传输文件(multipart form-data)