android viewpager实现轮播效果

本文是基于ViewPager实现的无限自动轮播banner,供大家参考,具体内容如下

分为四步去实现:

第一步是有限手动轮播;

第二步是无限轮播;

第三步是自动轮播;

第四步是指示器适配

第一步:有限手动轮播实现

布局:

<androidx.viewpager.widget.ViewPager     android:id="@+id/banner"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:layout_marginStart="12dp"     android:layout_marginEnd="12dp" />

adapter实现:

public class BannerAdapter extends PagerAdapter {     private List<String> bannerList;     public BannerAdapter(List<String> bannerList) {         this.bannerList = bannerList;     }     @Override     public int getCount() {         return bannerList.size();     }     @Override     public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {         return view == object;     }     @NonNull     @Override     public Object instantiateItem(@NonNull ViewGroup container, int position) {         ImageView bannerImageView = new ImageView(container.getContext());         ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);         bannerImageView.setLayoutParams(lp);         bannerImageView.setScaleType(ImageView.ScaleType.FIT_XY);         Glide.with(container.getContext()).load(bannerList.get(position)).into(bannerImageView);         container.addView(bannerImageView);         return bannerImageView;     }     @Override     public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {         container.removeView((View) object);     } }

Activity中:

// scrollview中viewpager一定要设置高度,此处根据图片的宽高比来设定高度 int bannerWidth = (Utils.getScreenWidth(getContext()) - Utils.dip2pixel(getContext(), 24)); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) bannerView.getLayoutParams(); lp.width = LinearLayout.LayoutParams.MATCH_PARENT; lp.height = (int) (bannerWidth * 90f / 345); bannerView.setLayoutParams(lp); bannerView.setAdapter(new BannerAdapter(getUrlList()));

注意:ScrollView包裹ViewPager时,ViewPager的高度一定要有确定值,否则内容无法加载出来,可以在xml中指定,也可以代码设定,但一定要有确定值。

第二步:无限轮播

无限轮播只需要在有限轮播的基础上,做以下两个改动点,修改getCount返回值且在加载数据时获取正确的数据源即可

public class BannerAdapter extends PagerAdapter {     private List<String> bannerList;     public BannerAdapter(List<String> bannerList) {         this.bannerList = bannerList;     }     @Override     public int getCount() { //        return bannerList.size();  // before         return Integer.MAX_VALUE;   // now     }     @Override     public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {         return view == object;     }     @NonNull     @Override     public Object instantiateItem(@NonNull ViewGroup container, int position) {         ImageView bannerImageView = new ImageView(container.getContext());         int realPosition = position % bannerList.size(); // 获取要加载数据的真实位置         ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);         bannerImageView.setLayoutParams(lp);         bannerImageView.setScaleType(ImageView.ScaleType.FIT_XY); //        Glide.with(container.getContext()).load(bannerList.get(position)).into(bannerImageView); // before         Glide.with(container.getContext()).load(bannerList.get(realPosition)).into(bannerImageView); // now         container.addView(bannerImageView);         return bannerImageView;     }     @Override     public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {         container.removeView((View) object);     } }

修改完发现banner只能向右无限轮播,第一次左滑滑不动,这个时候我们强制设置viewpager位置在中间就可以解决这个问题了

bannerView.setAdapter(new BannerAdapter(getUrlList())); bannerView.setCurrentItem(getUrlList().size() * 5);

第三步:自动轮播

handler每隔轮播间隔发送消息,设置viewpager为下一个位置

private Runnable bannerRunnable = new Runnable() {         @Override         public void run() {             bannerView.setCurrentItem(bannerView.getCurrentItem() + 1);             mHandler.postDelayed(bannerRunnable, 3000);         }     }; bannerView.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {             @Override             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {             }             @Override             public void onPageSelected(int position) {                 // 手滑动到某一位置,重新开始计时                 start();             }             @Override             public void onPageScrollStateChanged(int state) {             }         }); private void start() {         mHandler.removeCallbacksAndMessages(null);         mHandler.postDelayed(bannerRunnable, 3000);     }

第四步:添加指示器

指示器样式及表现可以自己去根据需求实现,以相对简单和常见的小圆圈指示器为例,添加和banner数量相同的小圆圈,小圆圈设置selector,在选中时为黑色选中样式,在非选中时为灰色默认样式,根据当前选中的banner的实际position,设置指示器的selected属性,从而展示不同的样式

private void initIndicator() {         for (int i = 0; i < getUrlList().size(); i++) {             View view = new View(getActivity());             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(Utils.dip2pixel(getActivity(), 6), Utils.dip2pixel(getActivity(), 6));             lp.rightMargin = Utils.dip2pixel(getActivity(), 8);             view.setLayoutParams(lp);             view.setBackgroundResource(R.drawable.selector_indicator_view);             view.setSelected(i == 0);             llIndicatorView.addView(view);         }     } private void initBannerView() {         bannerView.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {             @Override             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {             }             @Override             public void onPageSelected(int position) {                 // 手滑动到某一位置,重新开始计时                 realPosition = 0;                 realPosition = position % getUrlList().size();                 // 根据当前滑动到的banner设置指示器的状态                 for (int i = 0; i < llIndicatorView.getChildCount(); i++) {                     llIndicatorView.getChildAt(i).setSelected(i == realPosition);                 }                 start();             }             @Override             public void onPageScrollStateChanged(int state) {             }         });     }

附:Utils文件

public class Utils {     public static void setFullScreen(Activity activity) {         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {             ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();             decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);             activity.getWindow().setStatusBarColor(Color.TRANSPARENT);         }     }     public static int dip2pixel(Context context, float n) {         int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, n, context.getResources().getDisplayMetrics());         return value;     }     /**      * 获取屏幕宽度      * @param context      * @return 屏幕宽度      */     public static int getScreenWidth(Context context) {         WindowManager wm = (WindowManager) context                 .getSystemService(Context.WINDOW_SERVICE);         DisplayMetrics outMetrics = new DisplayMetrics();         wm.getDefaultDisplay().getMetrics(outMetrics);         return outMetrics.widthPixels;     } }

推荐阅读