您的位置:首页 > 移动开发 > Android开发

Android基础控件——Banner轮播图的无限循环轮播功能、手动滑动功能

2016-07-13 19:29 671 查看
Banner轮播图的无限循环轮播功能、手动滑动功能

轮播图实现:(假如5张图轮播)
1、在List中存好这5张图,传到ViewPager的Adapter中,相当于5张图片横铺在ViewPager控件中。
2、设置ViewPager一开始的起始位置为5*1000=5000,并用seletedBanner记录该位置。
3、在PagerAdapter中将其getCount方法返回Integer的最大值,让它向左向右滑都不会越界。
4、在PagerAdapter中必须对当前位置%5(由于5张图,%5结果在0-4之间,刚好是图片集合的下标,如5002%5=2,就是List[2]中的对象)。
5、ViewPager监听滚动事件,用seletedBanner记录新位置。
6、在onResume中开始轮播。
圆点实现:
1、在一个水平的布局中添加5个圆点View对象,并存入一个List中。
2、遍历圆点List,在ViewPager滚动回调中判断seletedBanner(当前位置)%5,则该得到的值为选中圆点,其他为未选中圆点。
其效果图:



实现步骤

1、自定义RelativeLayout,编写固定的构造方法
public class MyBannerView extends RelativeLayout implements View.OnTouchListener, ViewPager.OnPageChangeListener {

public MyBannerView(Context context) {
this(context, null);
}

public MyBannerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public MyBannerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//初始化工作
initBannerViews(context, attrs, defStyleAttr);
}
}

2、声明需要用到的变量
//轮播图控件
private ViewPager targetVp;
//轮播图集合
private ArrayList<View> bannerList;
//指示器图集合
private ArrayList<View> indicationList;
//上下文
private Context context;
//当前轮播图位置
private int selectedBanner;
//提示轮播
private final static int BANNER_CHANGE = 0;
//是否为网络图片加载,作用是:如果是网络图片加载就不滚动轮播图,让用户自己手动滑动轮播图
boolean isNetImg = false;

3、初始化用到的组件
private void initBannerViews(Context context, AttributeSet attrs, int defStyleAttr) {
this.context = context;
//初始化ViewPager
targetVp = new ViewPager(context);
targetVp.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
targetVp.setOnTouchListener(this);
targetVp.setOnPageChangeListener(this);
//添加到View中
addView(targetVp);
}

4、提供方法加载图片和指示器

这里有两个方法,加载本地图片和加载网络图片,加载网络图片用到Glide第三方框架,Glide的学习可以查看我的博客
/**
* 在本地Drawable中加载轮播图
*
* @param activity
* @param img_urls 轮播图drawable的ID
*/
public void initShowImageForLocal(Activity activity, int[] img_urls) {
//指示器布局
LinearLayout ly_indication = new LinearLayout(activity);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//指示器边距
params.bottomMargin = 15;
//指示器位置
params.addRule(ALIGN_PARENT_BOTTOM);
params.addRule(CENTER_HORIZONTAL);
//添加到View中
addView(ly_indication, params);
//图片集合和指示器集合
bannerList = new ArrayList<View>();
indicationList = new ArrayList<View>();
for (int i = 0; i < img_urls.length; i++) {
//初始化图片
ImageView iv = new ImageView(activity);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
iv.setBackgroundResource(img_urls[i]);
bannerList.add(iv);
//初始化指示器
ImageView iv2 = new ImageView(activity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(8, 0, 0, 0);
iv2.setLayoutParams(lp);
//初始化指示器默认为第一张高亮
if (i == 0) {
iv2.setBackgroundResource(R.drawable.home_top_ic_point_on);
} else {
iv2.setBackgroundResource(R.drawable.home_top_ic_point_off);
}
indicationList.add(iv2);
//添加到圆点布局
ly_indication.addView(iv2);
}
//初始化轮播Adapter
HomeBannerAdapter bannerAdapter = new HomeBannerAdapter(bannerList, activity);
targetVp.setAdapter(bannerAdapter);
//初始化当前位置
targetVp.setCurrentItem(bannerList.size() * 1000);
//当前position
selectedBanner = bannerList.size() * 1000;
}

/**
* 通过网络Url加载轮播图
*
* @param activity
* @param img_urls 网络图片的URL
*/
public void initShowImageForNet(Activity activity, List<String> img_urls) {
//标识是网络加载
isNetImg = true;
//指示器布局
LinearLayout ly_indication = new LinearLayout(activity);
LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
// 指示器边距
params.bottomMargin = 15;
//指示器位置
params.addRule(ALIGN_PARENT_BOTTOM);
params.addRule(CENTER_HORIZONTAL);
//添加到View中
addView(ly_indication, params);
//图片集合和指示器集合
bannerList = new ArrayList<View>();
indicationList = new ArrayList<View>();
for (int i = 0; i < img_urls.size(); i++) {
//初始化图片
ImageView iv = new ImageView(activity);
iv.setScaleType(ImageView.ScaleType.FIT_XY);
GlideUtils.setImageView(context, img_urls.get(i), iv);
bannerList.add(iv);
//初始化指示器
ImageView iv2 = new ImageView(activity);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(8, 0, 0, 0);
iv2.setLayoutParams(lp);
if (i == 0) {
iv2.setBackgroundResource(R.drawable.home_top_ic_point_on);
} else {
iv2.setBackgroundResource(R.drawable.home_top_ic_point_off);
}
indicationList.add(iv2);
//添加到圆点布局
ly_indication.addView(iv2);
}
//初始化轮播数据
HomeBannerAdapter bannerAdapter = new HomeBannerAdapter(bannerList, activity);
targetVp.setAdapter(bannerAdapter);
//初始化当前位置
targetVp.setCurrentItem(bannerList.size() * 1000);
//当前position
selectedBanner = bannerList.size() * 1000;
}

5、实现监听事件
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {
//改变当前位置指针
selectedBanner = position;
//改变指示器变化
bannerPointLight(position % indicationList.size());
}

@Override
public void onPageScrollStateChanged(int state) {

}

@Override
public boolean onTouch(View v, MotionEvent event) {
//如果是网络加载则没必要监听
if (isNetImg) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//结束轮播
mHandler.removeCallbacksAndMessages(null);
break;
case MotionEvent.ACTION_UP:
//开启轮播
mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
break;
case MotionEvent.ACTION_CANCEL:
//开启轮播
mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
break;
}
return false;
}

6、提供开启轮播和结束轮播的方法
/**
* 开始轮播
*/
public void startBanner() {
//开启轮播
mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
}

/**
* 结束轮播
*/
public void endBanner() {
//结束轮播
mHandler.removeCallbacksAndMessages(null);
}

7、处理轮播 /**
* 消息处理器
*/
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case BANNER_CHANGE:
//形成轮播循环
targetVp.setCurrentItem(selectedBanner + 1);
mHandler.sendEmptyMessageDelayed(BANNER_CHANGE, 3000);
break;
}
}
};

8、编写HomeBannerAdapter /**
* 适配器
*/
public class HomeBannerAdapter extends PagerAdapter {

private List<View> views;
private Context context;

public HomeBannerAdapter(List<View> views, Context context) {
this.context = context;
this.views = views;
}

public Object instantiateItem(View container, int position) {
final int currentItem = position % views.size();
((ViewPager) container).addView(views.get(currentItem));
return views.get(currentItem);
}

public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}

public int getCount() {
return Integer.MAX_VALUE;
}

public boolean isViewFromObject(View arg0, Object arg1) {
return (arg0 == arg1);
}
}

9、编写两个圆点的xml文件

① 红点
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">

<solid android:color="#FF5000"/>

<stroke
android:width="0.1dp"
android:color="#8888" />
<size
android:width="6dp"
android:height="6dp" />
</shape>

② 灰点<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">

<solid android:color="#88ffffff"/>

<stroke
android:width="0.1dp"
android:color="#8888" />
<size
android:width="6dp"
android:height="6dp" />
</shape>
10、接着就可以在Acitivity中使用我们的自定义的BannerView

① 编写布局文件,使用我们的自定义BannerView
<com.handsome.didi.View.MyBannerView
android:id="@+id/vp_banner"
android:layout_width="match_parent"
android:layout_height="120dp" />

② 在代码中找到对应ID控件,并且初始化vp_banner = findView(R.id.vp_banner);
vp_banner.initShowImageForNet(getActivity(), new ArrayList<String>{"","","",""});

③ 开启轮播和停止轮播 @Override
public void onResume() {
super.onResume();
//开始轮播
vp_banner.startBanner();
}

@Override
public void onPause() {
super.onPause();
//停止轮播
vp_banner.endBanner();
}

源码下载

源码下载说明
1、网络图片加载要用到第三库Glide
2、网络加载默认是不会自动轮播的,如果需要自动轮播需要将if(isNetImg){return false};去掉
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: