平时开发软件的时候,经常会碰到轮播图这样的需求,下面介绍一种轮播图的实现方式:
我把轮播图写成了一个自定义控件,需要集成Android Support Library v4包和谷歌推荐的一个图片加载库Glide:
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; import android.os.Handler; import android.os.Message; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Scroller; import com.bumptech.glide.Glide; public class BannerLayout extends RelativeLayout { private ViewPager pager; // 指示器容器 private LinearLayout indicatorContainer; // 未选中图片样式 private Drawable unSelectedDrawable; // 当前选中图片样式 private Drawable selectedDrawable; private int WHAT_AUTO_PLAY = 1000; // 是否自动轮播 private boolean isAutoPlay = true; private int itemCount; private int selectedIndicatorColor = 0xffff0000; private int unSelectedIndicatorColor = 0x88888888; private Shape indicatorShape = Shape.oval; private int selectedIndicatorHeight = 6; private int selectedIndicatorWidth = 6; private int unSelectedIndicatorHeight = 6; private int unSelectedIndicatorWidth = 6; private Position indicatorPosition = Position.centerBottom; // 轮播的间隔时间 private int autoPlayDuration = 4000; private int scrollDuration = 900; private int indicatorSpace = 3; private int indicatorMargin = 10; private int defaultImage; // 指示器的样式 private enum Shape { rect, oval } // 指示器的位置 private enum Position { centerBottom, rightBottom, leftBottom, centerTop, rightTop, leftTop } private OnBannerItemClickListener onBannerItemClickListener; private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == WHAT_AUTO_PLAY) { if (pager != null) { pager.setCurrentItem(pager.getCurrentItem() + 1, true); handler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration); } } return false; } }); public BannerLayout(Context context) { super(context); init(null, 0); } public BannerLayout(Context context, AttributeSet attrs) { super(context, attrs); init(attrs, 0); } public BannerLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(attrs, defStyleAttr); } private void init(AttributeSet attrs, int defStyle) { TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.BannerLayoutStyle, defStyle, 0); selectedIndicatorColor = array.getColor( R.styleable.BannerLayoutStyle_selectedIndicatorColor, selectedIndicatorColor); unSelectedIndicatorColor = array.getColor( R.styleable.BannerLayoutStyle_unSelectedIndicatorColor, unSelectedIndicatorColor); int shape = array.getInt(R.styleable.BannerLayoutStyle_indicatorShape, Shape.oval.ordinal()); for (Shape shape1 : Shape.values()) { if (shape1.ordinal() == shape) { indicatorShape = shape1; break; } } selectedIndicatorHeight = (int) array.getDimension( R.styleable.BannerLayoutStyle_selectedIndicatorHeight, selectedIndicatorHeight); selectedIndicatorWidth = (int) array.getDimension( R.styleable.BannerLayoutStyle_selectedIndicatorWidth, selectedIndicatorWidth); unSelectedIndicatorHeight = (int) array.getDimension( R.styleable.BannerLayoutStyle_unSelectedIndicatorHeight, unSelectedIndicatorHeight); unSelectedIndicatorWidth = (int) array.getDimension( R.styleable.BannerLayoutStyle_unSelectedIndicatorWidth, unSelectedIndicatorWidth); int position = array.getInt( R.styleable.BannerLayoutStyle_indicatorPosition, Position.centerBottom.ordinal()); for (Position position1 : Position.values()) { if (position == position1.ordinal()) { indicatorPosition = position1; } } indicatorSpace = (int) array.getDimension( R.styleable.BannerLayoutStyle_indicatorSpace, indicatorSpace); indicatorMargin = (int) array.getDimension( R.styleable.BannerLayoutStyle_indicatorMargin, indicatorMargin); autoPlayDuration = array.getInt( R.styleable.BannerLayoutStyle_autoPlayDuration, autoPlayDuration); scrollDuration = array.getInt( R.styleable.BannerLayoutStyle_scrollDuration, scrollDuration); isAutoPlay = array.getBoolean(R.styleable.BannerLayoutStyle_isAutoPlay, isAutoPlay); defaultImage = array.getResourceId( R.styleable.BannerLayoutStyle_defaultImage, defaultImage); array.recycle(); // 绘制未选中状态图形 LayerDrawable unSelectedLayerDrawable; LayerDrawable selectedLayerDrawable; GradientDrawable unSelectedGradientDrawable; unSelectedGradientDrawable = new GradientDrawable(); // 绘制选中状态图形 GradientDrawable selectedGradientDrawable; selectedGradientDrawable = new GradientDrawable(); switch (indicatorShape) { case rect: unSelectedGradientDrawable.setShape(GradientDrawable.RECTANGLE); selectedGradientDrawable.setShape(GradientDrawable.RECTANGLE); break; case oval: unSelectedGradientDrawable.setShape(GradientDrawable.OVAL); selectedGradientDrawable.setShape(GradientDrawable.OVAL); break; } unSelectedGradientDrawable.setColor(unSelectedIndicatorColor); unSelectedGradientDrawable.setSize(unSelectedIndicatorWidth, unSelectedIndicatorHeight); unSelectedLayerDrawable = new LayerDrawable( new Drawable[] { unSelectedGradientDrawable }); unSelectedDrawable = unSelectedLayerDrawable; selectedGradientDrawable.setColor(selectedIndicatorColor); selectedGradientDrawable.setSize(selectedIndicatorWidth, selectedIndicatorHeight); selectedLayerDrawable = new LayerDrawable( new Drawable[] { selectedGradientDrawable }); selectedDrawable = selectedLayerDrawable; } // 添加本地图片路径 public void setViewRes(List<Integer> viewRes) { List<View> views = new ArrayList<View>(); itemCount = viewRes.size(); // 主要是解决当item为小于3个的时候滑动有问题,这里将其拼凑成3个以上 if (itemCount < 1) {// 当item个数0 throw new IllegalStateException("item count not equal zero"); } else if (itemCount < 2) {// 当item个数为1 views.add(getImageView(viewRes.get(0), 0)); views.add(getImageView(viewRes.get(0), 0)); views.add(getImageView(viewRes.get(0), 0)); } else if (itemCount < 3) {// 当item个数为2 views.add(getImageView(viewRes.get(0), 0)); views.add(getImageView(viewRes.get(1), 1)); views.add(getImageView(viewRes.get(0), 0)); views.add(getImageView(viewRes.get(1), 1)); } else { for (int i = 0; i < viewRes.size(); i++) { views.add(getImageView(viewRes.get(i), i)); } } setViews(views); } private ImageView getImageView(Integer res, final int position) { ImageView imageView = new ImageView(getContext()); imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onBannerItemClickListener != null) { onBannerItemClickListener.onItemClick(position); } } }); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); Glide.with(getContext()).load(res).centerCrop().into(imageView); return imageView; } // 添加网络图片路径 public void setViewUrls(List<String> urls) { List<View> views = new ArrayList<View>(); itemCount = urls.size(); // 主要是解决当item为小于3个的时候滑动有问题,这里将其拼凑成3个以上 if (itemCount < 1) {// 当item个数0 throw new IllegalStateException("item count not equal zero"); } else if (itemCount < 2) { // 当item个数为1 views.add(getImageView(urls.get(0), 0)); views.add(getImageView(urls.get(0), 0)); views.add(getImageView(urls.get(0), 0)); } else if (itemCount < 3) {// 当item个数为2 views.add(getImageView(urls.get(0), 0)); views.add(getImageView(urls.get(1), 1)); views.add(getImageView(urls.get(0), 0)); views.add(getImageView(urls.get(1), 1)); } else { for (int i = 0; i < urls.size(); i++) { views.add(getImageView(urls.get(i), i)); } } setViews(views); } private ImageView getImageView(String url, final int position) { ImageView imageView = new ImageView(getContext()); imageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onBannerItemClickListener != null) { onBannerItemClickListener.onItemClick(position); } } }); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); if (defaultImage != 0) { Glide.with(getContext()).load(url).placeholder(defaultImage) .centerCrop().into(imageView); } else { Glide.with(getContext()).load(url).centerCrop().into(imageView); } return imageView; } // 添加任意View视图 private void setViews(final List<View> views) { // 初始化pager pager = new ViewPager(getContext()); // 添加viewpager到SliderLayout addView(pager); setSliderTransformDuration(scrollDuration); // 初始化indicatorContainer indicatorContainer = new LinearLayout(getContext()); indicatorContainer.setGravity(Gravity.CENTER_VERTICAL); RelativeLayout.LayoutParams params = new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); switch (indicatorPosition) { case centerBottom: params.addRule(RelativeLayout.CENTER_HORIZONTAL); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); break; case centerTop: params.addRule(RelativeLayout.CENTER_HORIZONTAL); params.addRule(RelativeLayout.ALIGN_PARENT_TOP); break; case leftBottom: params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); break; case leftTop: params.addRule(RelativeLayout.ALIGN_PARENT_LEFT); params.addRule(RelativeLayout.ALIGN_PARENT_TOP); break; case rightBottom: params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); break; case rightTop: params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); params.addRule(RelativeLayout.ALIGN_PARENT_TOP); break; } // 设置margin params.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin); // 添加指示器容器布局到SliderLayout addView(indicatorContainer, params); // 初始化指示器,并添加到指示器容器布局 for (int i = 0; i < itemCount; i++) { ImageView indicator = new ImageView(getContext()); indicator.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); indicator.setPadding(indicatorSpace, indicatorSpace, indicatorSpace, indicatorSpace); indicator.setImageDrawable(unSelectedDrawable); indicatorContainer.addView(indicator); } LoopPagerAdapter pagerAdapter = new LoopPagerAdapter(views); pager.setAdapter(pagerAdapter); // 设置当前item到Integer.MAX_VALUE中间的一个值,看起来像无论是往前滑还是往后滑都是ok的 // 如果不设置,用户往左边滑动的时候已经划不动了 int targetItemPosition = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % itemCount; pager.setCurrentItem(targetItemPosition); switchIndicator(targetItemPosition % itemCount); pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { switchIndicator(position % itemCount); } }); startAutoPlay(); } public void setSliderTransformDuration(int duration) { try { Field mScroller = ViewPager.class.getDeclaredField("mScroller"); mScroller.setAccessible(true); FixedSpeedScroller scroller = new FixedSpeedScroller( pager.getContext(), null, duration); mScroller.set(pager, scroller); } catch (Exception e) { e.printStackTrace(); } } /** * 开始自动轮播 */ public void startAutoPlay() { stopAutoPlay(); // 避免重复消息 if (isAutoPlay) { handler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration); } } @Override protected void onWindowVisibilityChanged(int visibility) { super.onWindowVisibilityChanged(visibility); if (visibility == VISIBLE) { startAutoPlay(); } else { stopAutoPlay(); } } /** * 停止自动轮播 */ public void stopAutoPlay() { if (isAutoPlay) { handler.removeMessages(WHAT_AUTO_PLAY); } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: stopAutoPlay(); break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: startAutoPlay(); break; } return super.dispatchTouchEvent(ev); } /** * 切换指示器状态 * * @param currentPosition * 当前位置 */ private void switchIndicator(int currentPosition) { for (int i = 0; i < indicatorContainer.getChildCount(); i++) { ((ImageView) indicatorContainer.getChildAt(i)) .setImageDrawable(i == currentPosition ? selectedDrawable : unSelectedDrawable); } } public void setOnBannerItemClickListener( OnBannerItemClickListener onBannerItemClickListener) { this.onBannerItemClickListener = onBannerItemClickListener; } public interface OnBannerItemClickListener { void onItemClick(int position); } public class LoopPagerAdapter extends PagerAdapter { private List<View> views; public LoopPagerAdapter(List<View> views) { this.views = views; } @Override public int getCount() { // Integer.MAX_VALUE = 2147483647 return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { if (views.size() > 0) { // position % view.size()是指虚拟的position会在[0,view.size())之间循环 View view = views.get(position % views.size()); if (container.equals(view.getParent())) { container.removeView(view); } container.addView(view); return view; } return null; } @Override public void destroyItem(ViewGroup container, int position, Object object) { } } public class FixedSpeedScroller extends Scroller { private int mDuration = 1000; public FixedSpeedScroller(Context context) { super(context); } public FixedSpeedScroller(Context context, Interpolator interpolator) { super(context, interpolator); } public FixedSpeedScroller(Context context, Interpolator interpolator, int duration) { this(context, interpolator); mDuration = duration; } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { // Ignore received duration, use fixed one instead super.startScroll(startX, startY, dx, dy, mDuration); } @Override public void startScroll(int startX, int startY, int dx, int dy) { // Ignore received duration, use fixed one instead super.startScroll(startX, startY, dx, dy, mDuration); } } }
自定义控件的属性定义:
<resources> <declare-styleable name="BannerLayoutStyle"> <attr name="selectedIndicatorColor" format="color|reference" /> <attr name="unSelectedIndicatorColor" format="color|reference" /> <attr name="indicatorShape" format="enum"> <enum name="rect" value="0" /> <enum name="oval" value="1" /> </attr> <attr name="selectedIndicatorHeight" format="dimension|reference" /> <attr name="selectedIndicatorWidth" format="dimension|reference" /> <attr name="unSelectedIndicatorHeight" format="dimension|reference" /> <attr name="unSelectedIndicatorWidth" format="dimension|reference" /> <attr name="indicatorPosition" format="enum"> <enum name="centerBottom" value="0" /> <enum name="rightBottom" value="1" /> <enum name="leftBottom" value="2" /> <enum name="centerTop" value="3" /> <enum name="rightTop" value="4" /> <enum name="leftTop" value="5" /> </attr> <attr name="indicatorSpace" format="dimension|reference" /> <attr name="indicatorMargin" format="dimension|reference" /> <attr name="autoPlayDuration" format="integer|reference" /> <attr name="scrollDuration" format="integer|reference" /> <attr name="isAutoPlay" format="boolean"/> <attr name="defaultImage" format="integer|reference"/> </declare-styleable> </resources>
轮播图控件的使用:
BannerLayout bannerLayout = (BannerLayout) findViewById(R.id.banner); BannerLayout bannerLayout2 = (BannerLayout) findViewById(R.id.banner2); // 加载网络图片 final List<String> urls = new ArrayList<String>(); urls.add("http://img4.duitang.com/uploads/item/201408/30/20140830185433_FnJLA.jpeg"); urls.add("http://img0.imgtn.bdimg.com/it/u=3379522155,2601893953&fm=21&gp=0.jpg"); urls.add("http://img3.imgtn.bdimg.com/it/u=3269141824,887330507&fm=21&gp=0.jpg"); urls.add("http://img4.imgtn.bdimg.com/it/u=3099510203,1072263599&fm=21&gp=0.jpg"); urls.add("http://img4.imgtn.bdimg.com/it/u=2943793272,3641314298&fm=21&gp=0.jpg"); bannerLayout.setViewUrls(urls); // 添加监听事件 bannerLayout .setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() { @Override public void onItemClick(int position) { Toast.makeText(MainActivity.this, String.valueOf(position), Toast.LENGTH_SHORT) .show(); } }); // 低于三张,加载本地图片 final List<Integer> urls2 = new ArrayList<Integer>(); urls2.add(R.drawable.loading_bg_guid1); urls2.add(R.drawable.loading_bg_guid2); bannerLayout2.setViewRes(urls2);
相关推荐
本示例"轮播图实现demo"旨在教你如何使用UIImageView、UIPageControl、NSTimer以及UIScrollView这四个关键组件来创建一个自动循环播放的图片展示功能。 首先,UIImageView是iOS中用于显示图像的视图。在这个轮播图...
本压缩包“轮播图实现过程.rar”提供了实现轮播图的完整流程,包括图片和操作代码,适用于在浏览器环境或Visual Studio Code (VScode) 等开发环境中进行实践。 轮播图的核心技术主要包括JavaScript和DOM操作。...
自动播放轮播图会在设定的时间间隔后自动切换图片。这种效果可以通过JavaScript定时器实现,jQuery的`.delay()`和`.animate()`方法可以用来控制过渡动画。同时,用户应该能通过点击按钮暂停或恢复自动播放。 4. **...
在Android开发中,轮播图(Carousel)是一种常见的UI组件,通常用于展示广告、推荐内容或者图片展示等。本篇文章将深入探讨如何在Android中实现一个功能完善的轮播图,主要涉及的技术点包括自定义ViewPager、...
在网页设计中,轮播图是一种常见的展示多张图片或内容的方式,它允许用户通过滑动或自动切换来查看不同的信息。在这个特定的场景中,我们关注的是如何使用JavaScript、CSS和HTML来实现一个简单的轮播图,并且具有...
- 图片切换:使用DOM操作(如`getElementById`、`getElementsByClassName`或`querySelector`等)选取需要切换的元素,然后改变其样式(如`display`属性)来实现图片的切换。 - 指示器和导航箭头:如果存在,可以...
在Android开发中,ViewPager是一种常用的组件,用于展示可滑动的页面集合,常用于实现诸如广告轮播图、Tab切换等效果。在这个“安卓ViewPager广告轮播图实现无限轮播”的示例中,我们将深入探讨如何利用ViewPager...
【标题】:“网易云轮播图实现完整代码”是指一种使用JavaScript和DOM操作技术来创建类似网易云音乐APP中常见的动态轮播图片效果的实践项目。这个“小demo”是作者在学习JavaScript过程中编写的,虽然可能在代码规范...
- 自动播放:轮播图可以设置定时器自动切换,以展示下一幅图片。 - 滑动切换:用户可以通过点击左右箭头或者手势滑动来切换图片。 - 图片适应:轮播图应能适应不同的屏幕尺寸,保持图片的适当比例显示。 2. **...
4. **插件与框架**:有许多现成的轮播图插件,如Bootstrap的carousel组件,Swiper.js,Slick等,它们提供了丰富的选项和自定义能力,可以快速实现复杂的轮播图效果,节省开发时间。 5. **响应式设计**:在现代网页...
本教程将详细介绍如何利用ViewPager来实现一个功能完备的Android轮播图,包括底部图片指示器、左右滑动箭头以及自动切换和交互控制。 **1. ViewPager基础知识** ViewPager是Android SDK中的一个强大的视图滑动容器...
在Android应用开发中,"画廊循环轮播图实现"是一项常见的需求,通常用于展示广告、产品图片或者任何需要连续滚动的内容。这个话题涉及到的主要技术是`ViewPager`和自定义指示器,以及如何实现无限循环的效果。下面...
总结来说,这个“轮播图实现广告条”的项目为安卓开发人员提供了一个实用的轮播图组件,它具备手动滑动切换、自动轮播、无限轮播和指示点等功能,且代码简洁,适合快速集成到项目中。通过研究这个项目,开发者可以...
采用ViewPager实现的广告轮播图,可以实现无限轮播,代码结构清晰易懂
轮播图(Carousel)是一种常见的UI设计元素,用于展示多张图片或内容并允许用户通过滑动或点击在这些内容之间切换。在这个“轮播图实现demo.zip”中,我们看到一个基本的轮播图实现,它具备了基础的功能,但没有实现...
在前端开发中,轮播图(Carousel)是一种常见的网页元素,用于展示一组可滑动切换的图片或内容。本资源包含纯JavaScript实现的三种不同类型的轮播图,这对于熟悉JavaScript和想要提升前端技能的开发者来说,是一份...
janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现janacsript轮播图的实现...
本资源提供的"安卓图片轮播广告轮播自动滚屏相关-广告轮播图实现左右无限循环动态添加小点标示集成简单.rar"应该包含一个简单的实现这一功能的代码示例。以下将详细解析这个主题中的关键知识点: 1. **图片轮播组件...
2. 图片切换动画:使用CSS过渡效果或JavaScript的`setTimeout`函数实现平滑的图片切换。 3. 点状指示器:创建与图片数量相同的点,并根据当前显示的图片更新对应的点的激活状态。 4. 用户交互:添加鼠标悬停暂停轮播...
本文实例为大家分享了jQuery实现轮播图及其原理的具体代码,供大家参考,具体内容如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8" name="viewport" content="width=device-width,...