热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Android实现带指示点的自动轮播无限循环效果

这篇文章主要为大家详细介绍了Android实现带指示点的自动轮播无限循环效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

想要实现无限轮播,一直向左滑动,当到最后一个view时,会滑动到第一个,无限…

可以自己写ViewPager然后加handler先实现自动滚动,当然这里我为了项目的进度直接使用了Trinea的Android-auto-scroll-view-pager库,网址:点击进入github 引用库compile('cn.trinea.android.view.autoscrollviewpager:android-auto-scroll-view-pager:1.1.2') {
exclude module: 'support-v4'
之后

1布局为

 
 
 
 
 

2 构建PagerAdapter
继承自RecyclingPagerAdapter (后面会贴出来源码)

 `public class Indicator1Adapter extends RecyclingPagerAdapter {
 private List imageIdList;
 Context context;
 //是否循环(创造构造方法,在activity里设置是否)
 //集合大小
 private int size;

 public Indicator1Adapter(List mData, Context context) {
  this.imageIdList = mData;
  this.cOntext= context;
  this.size = mData.size();
  isInfiniteLoop = false;
 }
 @Override
 public int getCount() {
 //是:最大(让集合的长度无限,从而模拟无限循环) 否,集合长度
  return isInfiniteLoop ? Integer.MAX_VALUE : imageIdList.size();
 }

 /**
  * @return the isInfiniteLoop
  */
 public boolean isInfiniteLoop() {
  return isInfiniteLoop;
 }

 /**
  * @param是否无限循环
  */
 public Indicator1Adapter setInfiniteLoop(boolean isInfiniteLoop) {
  this.isInfiniteLoop = isInfiniteLoop;
  return this;
 }

 /**
  * 真实的position
  *
  * @param position
  * @return
  */
 private int getPosition(int position) {
  return isInfiniteLoop ? position % size : position;
 }
 @Override
 public View getView(int position, View view, ViewGroup container) {
  ViewHolder holder;
  if (view == null) {
   holder = new ViewHolder();
   view = holder.imageView = new ImageView(context);
   view.setTag(holder);
  } else {
   holder = (ViewHolder)view.getTag();
  }
  holder.imageView.setImageResource(imageIdList.get(getPosition(position)));
  holder.imageView.setScaleType(ImageView.ScaleType.FIT_XY);
  return view;
 }

 private static class ViewHolder {

  ImageView imageView;
 }
}

3 在activity里或者fragment里就可以设置ViewPager

定义的成员变量:

//viewpager1
 @BindView(R.id.viewpager1)
 AutoScrollViewPager mPager1;
 //承载小点点的控件容器(布局里有)
 @BindView(R.id.ll_dot1)
 LinearLayout mLlDot1;
Indicator1Adapter adapter1 = new Indicator1Adapter( mData,act).setInfiniteLoop(true);//开启无限循环
  mPager1.setAdapter(adapter1);
  mPager1.setInterval(PLAY_TIME);//轮播时间间隔
  mPager1.startAutoScroll();//开启自动轮播
  mPager1.setCurrentItem(Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mData.size());

然后你嫌弃官方的换图间隔时间太短,一闪而过,可以通过反射 设置

//通过反射让滚动速度为自己的喜好的(这里设为1.2s)
  try {
   Field field = ViewPager.class.getDeclaredField("mScroller");
   field.setAccessible(true);
   FixedSpeedScroller scroller = new FixedSpeedScroller(mPager1.getContext(),
     new AccelerateInterpolator());
   field.set(mPager1, scroller);
   scroller.setmDuration(1200);
  } catch (Exception e) {
   Log.e(TAG, "Exception", e);
  }

4 然后我们的小点点还没有使用呢
这里我写了方法:

/**
 * 设置状态点1
 */
 private void setOvalLayout1() {
  for (int i = 0; i 

别忘了重写

 @Override
 public void onPause() {
  super.onPause();
  // stop auto scroll when onPause
  mPager1.stopAutoScroll();
 }

 @Override
 public void onResume() {
  super.onResume();
  // start auto scroll when onResume
  mPager1.startAutoScroll();
 }

好了,无限循环自动轮播,完成了.

5点点布局:


 
 

6 点点的background
dot_normal.xml

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 

 


dot_selected.xml

<&#63;xml version="1.0" encoding="utf-8"&#63;>

 
 

RecyclingPagerAdapter的源码依赖RecycleBin类,一并贴出来

public class RecycleBin {
 /**
 * Views that were on screen at the start of layout. This array is populated at the start of
 * layout, and at the end of layout all view in activeViews are moved to scrapViews.
 * Views in activeViews represent a contiguous range of Views, with position of the first
 * view store in mFirstActivePosition.
 */
 private View[] activeViews = new View[0];
 private int[] activeViewTypes = new int[0];

 /** Unsorted views that can be used by the adapter as a convert view. */
 private SparseArray[] scrapViews;

 private int viewTypeCount;

 private SparseArray currentScrapViews;

 public void setViewTypeCount(int viewTypeCount) {
 if (viewTypeCount <1) {
  throw new IllegalArgumentException("Can't have a viewTypeCount <1");
 }
 //noinspection unchecked
 SparseArray[] scrapViews = new SparseArray[viewTypeCount];
 for (int i = 0; i ();
 }
 this.viewTypeCount = viewTypeCount;
 currentScrapViews = scrapViews[0];
 this.scrapViews = scrapViews;
 }

 protected boolean shouldRecycleViewType(int viewType) {
 return viewType >= 0;
 }

 /** @return A view from the ScrapViews collection. These are unordered. */
 View getScrapView(int position, int viewType) {
 if (viewTypeCount == 1) {
  return retrieveFromScrap(currentScrapViews, position);
 } else if (viewType >= 0 && viewType = Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
  scrap.setAccessibilityDelegate(null);
 }
 }

 /** Move all views remaining in activeViews to scrapViews. */
 void scrapActiveViews() {
 final View[] activeViews = this.activeViews;
 final int[] activeViewTypes = this.activeViewTypes;
 final boolean multipleScraps = viewTypeCount > 1;

 SparseArray scrapViews = currentScrapViews;
 final int count = activeViews.length;
 for (int i = count - 1; i >= 0; i--) {
  final View victim = activeViews[i];
  if (victim != null) {
  int whichScrap = activeViewTypes[i];

  activeViews[i] = null;
  activeViewTypes[i] = -1;

  if (!shouldRecycleViewType(whichScrap)) {
   continue;
  }

  if (multipleScraps) {
   scrapViews = this.scrapViews[whichScrap];
  }
  scrapViews.put(i, victim);

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
   victim.setAccessibilityDelegate(null);
  }
  }
 }

 pruneScrapViews();
 }

 /**
 * Makes sure that the size of scrapViews does not exceed the size of activeViews.
 * (This can happen if an adapter does not recycle its views).
 */
 private void pruneScrapViews() {
 final int maxViews = activeViews.length;
 final int viewTypeCount = this.viewTypeCount;
 final SparseArray[] scrapViews = this.scrapViews;
 for (int i = 0; i  scrapPile = scrapViews[i];
  int size = scrapPile.size();
  final int extras = size - maxViews;
  size--;
  for (int j = 0; j  scrapViews, int position) {
 int size = scrapViews.size();
 if (size > 0) {
  // See if we still have a view for this position.
  for (int i = 0; i 

RecyclingPagerAdapter

public abstract class RecyclingPagerAdapter extends PagerAdapter {
 static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;

 private final RecycleBin recycleBin;

 public RecyclingPagerAdapter() {
 this(new RecycleBin());
 }

 RecyclingPagerAdapter(RecycleBin recycleBin) {
 this.recycleBin = recycleBin;
 recycleBin.setViewTypeCount(getViewTypeCount());
 }

 @Override public void notifyDataSetChanged() {
 recycleBin.scrapActiveViews();
 super.notifyDataSetChanged();
 }

 @Override public final Object instantiateItem(ViewGroup container, int position) {
 int viewType = getItemViewType(position);
 View view = null;
 if (viewType != IGNORE_ITEM_VIEW_TYPE) {
  view = recycleBin.getScrapView(position, viewType);
 }
 view = getView(position, view, container);
 container.addView(view);
 return view;
 }

 @Override public final void destroyItem(ViewGroup container, int position, Object object) {
 View view = (View) object;
 container.removeView(view);
 int viewType = getItemViewType(position);
 if (viewType != IGNORE_ITEM_VIEW_TYPE) {
  recycleBin.addScrapView(view, position, viewType);
 }
 }

 @Override public final boolean isViewFromObject(View view, Object object) {
 return view == object;
 }

 /**
 * 

* Returns the number of types of Views that will be created by * {@link #getView}. Each type represents a set of views that can be * converted in {@link #getView}. If the adapter always returns the same * type of View for all items, this method should return 1. *

*

* This method will only be called when when the adapter is set on the * the {@link AdapterView}. *

* * @return The number of types of Views that will be created by this adapter */ public int getViewTypeCount() { return 1; } /** * Get the type of View that will be created by {@link #getView} for the specified item. * * @param position The position of the item within the adapter's data set whose view type we * want. * @return An integer representing the type of View. Two views should share the same type if one * can be converted to the other in {@link #getView}. Note: Integers must be in the * range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can * also be returned. * @see #IGNORE_ITEM_VIEW_TYPE */ @SuppressWarnings("UnusedParameters") // Argument potentially used by subclasses. public int getItemViewType(int position) { return 0; } /** * Get a View that displays the data at the specified position in the data set. You can either * create a View manually or inflate it from an XML layout file. When the View is inflated, the * parent View (GridView, ListView...) will apply default layout parameters unless you use * {@link android.view.LayoutInflater#inflate(int, ViewGroup, boolean)} * to specify a root view and to prevent attachment to the root. * * @param position The position of the item within the adapter's data set of the item whose view * we want. * @param convertView The old view to reuse, if possible. Note: You should check that this view * is non-null and of an appropriate type before using. If it is not possible to convert * this view to display the correct data, this method can create a new view. * Heterogeneous lists can specify their number of view types, so that this View is * always of the right type (see {@link #getViewTypeCount()} and * {@link #getItemViewType(int)}). * @return A View corresponding to the data at the specified position. */ public abstract View getView(int position, View convertView, ViewGroup container); }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 解决微信电脑版无法刷朋友圈问题:使用安卓远程投屏方案
    在工作期间想要浏览微信和朋友圈却不太方便?虽然微信电脑版目前不支持直接刷朋友圈,但通过远程投屏技术,可以轻松实现在电脑上操作安卓设备的功能。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文深入探讨了 com.example.android.sunshine.data.TestUtilities 中 validateThenCloseCursor() 方法的使用方法及其代码示例,旨在帮助开发者更好地理解和应用该方法。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
author-avatar
我的小角落5
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有