轮播条控件是最常用的一种控件,以前在都是在github上找来直接用的,今天我来自定义一个自己的轮播控件。
完成图片滑动
我将轮播控件分为几个模块,首先完成图片的轮转
- 继承ViewPager
- 建立init()方法进行初始化,并设置适配器,代码如下
public class AutoScrollViewPager extends ViewPager{
private List<String> imgUrl;//图片地址
private ImageLoadCache imageLoadCache;
public void setImgUrl(List<String> imgUrl) {
this.imgUrl = imgUrl;
}
public AutoScrollViewPager(Context context) {
super(context);
}
public AutoScrollViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void init(){
imageLoadCache = new ImageLoadCache(getContext());
this.setAdapter(new MyPagerAdapter());
}
/**
* ViewPager的适配器
*/
class MyPagerAdapter extends PagerAdapter{
@Override
public int getCount() {
return imgUrl.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(getContext());
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);//设置图片显示样式
//设置布局参数
ViewPager.LayoutParams params = new LayoutParams();
params.width = ViewPager.LayoutParams.MATCH_PARENT;
params.height = ViewPager.LayoutParams.MATCH_PARENT;
//加载图片
imageLoadCache.displayImage(imageView,imgUrl.get(position));
//将imageView加入到容器中
container.addView(imageView,params);
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//将ImageView从容器中移除
container.removeView((View) object);
}
}
添加指示器
因为指示器的个数是随图片的数量增加而增加的,因此指示器是动态生成的
修改布局
总布局如下
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp">
<com.dmzj.akitajyx.circleprogressbar.AutoScrollViewPager
android:id="@+id/au"
android:layout_width="match_parent"
android:layout_height="180dp">
</com.dmzj.akitajyx.circleprogressbar.AutoScrollViewPager>
<LinearLayout
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#eee58f">
<!--标题-->
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="我是标题"
android:textSize="15sp"/>
<!--指示器的父容器-->
<LinearLayout
android:id="@+id/lll_dot"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
</LinearLayout>
</RelativeLayout>
修改init()方法
public void init(int pageNum,LinearLayout layout){
pageCount = pageNum;//得到总页数
for (int i = 0; i < pageCount; i++) {
ImageView imageView = new ImageView(getContext());
imageView.setBackgroundResource(R.drawable.dot_selector);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
params.rightMargin = 6;//设置指示器之间的距离
imageViews.add(imageView);
layout.addView(imageView,params);
}
imageViews.get(0).setSelected(true);//默认第一个选中
imageLoadCache = new ImageLoadCache(getContext());
this.setAdapter(new MyPagerAdapter());
}
在MainActivity中这样调用
autoScrollViewPager = (AutoScrollViewPager) findViewById(R.id.au);
layout = (LinearLayout) findViewById(R.id.lll_dot);
autoScrollViewPager.setImgUrl(img);
autoScrollViewPager.init(img.size(),layout);
效果如下
指示器随图片滑动而滑动
要想达成这个效果,我们必须重写ViewPage的OnPageChangeListener的方法
/**
* 页面切换监听器
*/
class MyPageChangeListener implements OnPageChangeListener{
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
//修改上一个的状态
imageViews.get(currentPage).setSelected(false);
//更新新的未位置
currentPage = position;
//修改当前位置指示器的状态
imageViews.get(currentPage).setSelected(true);
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
然后在init()中加入
this.setOnPageChangeListener(new MyPageChangeListener());
效果如下
添加标题
首先加入如下代码
private List<String> titles;
private TextView textView;
public void setTitles(List<String> titles,TextView textView) {
this.titles = titles;
this.textView = textView;
textView.setText(titles.get(0));//默认设置第一个标题
}
在往自定义的OnPageChangeListener中修改为
@Override
public void onPageSelected(int position) {
//修改上一个的状态
imageViews.get(currentPage).setSelected(false);
//更新新的未位置
currentPage = position;
//修改当前位置指示器的状态
imageViews.get(currentPage).setSelected(true);
if (titles!=null && textView!=null){
textView.setText(titles.get(position));
}
}
最后在MainActivity中
autoScrollViewPager = (AutoScrollViewPager) findViewById(R.id.au);
textView = (TextView) findViewById(R.id.tv_title);
layout = (LinearLayout) findViewById(R.id.lll_dot);
autoScrollViewPager.setImgUrl(img);
autoScrollViewPager.setTitles(strings,textView);
autoScrollViewPager.init(img.size(),layout);
效果如下
添加无限滚动
为了使控件的扩展性变得更强,我增加无限轮播的功能,可让使用者自定义
private boolean isLooping = false;//是否启用自动轮播,默认为false
public void setLooping(boolean looping) {
isLooping = looping;
}
修改ViewPage的适配器,在取加载图片的地方对位置做取余操作,让下标不越界
imageLoadCache.displayImage(imageView,imgUrl.get(position%pageCount));
修改OnPageChangeListener
//修改上一个的状态
imageViews.get(currentPage%pageCount).setSelected(false);
//更新新的未位置
currentPage = position;
//修改当前位置指示器的状态
imageViews.get(currentPage%pageCount).setSelected(true);
if (titles!=null && textView!=null){
textView.setText(titles.get(position%pageCount));
}
效果如下
添加点击事件
在一般的轮播图的功能中,大多数是点击进入详情页,因此在这,我给控件增加点击事件
首先增加
private OnItemClickListener itemClickListener;
public interface OnItemClickListener{
void itemClickListener(int postion);
}
public void setItemClickListener(OnItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
再是重写OnTouchListener
/**
* 页面触摸监听器
*/
class MyOnTouchListener implements OnTouchListener{
int downx;
long downTime;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
downx = (int) getX();
downTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
int upx = (int) getX();
if (downx==upx && System.currentTimeMillis() - downTime<300){
if (itemClickListener!=null){
itemClickListener.itemClickListener(currentPage%pageCount);
}
}
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}
在MyPagerAdapter中设置
imageView.setOnTouchListener(new MyOnTouchListener());
在MainActivity中调用
autoScrollViewPager.setItemClickListener(new AutoScrollViewPager.OnItemClickListener() {
@Override
public void itemClickListener(int postion) {
Toast.makeText(getBaseContext(),"第"+postion,Toast.LENGTH_SHORT).show();
}
});
效果如下
增加自动轮播
最后我们增加自动轮播功能使控件更强大
private boolean isAutoScroll = false;//默认不开启自动轮播
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==1){
int index = getCurrentItem();
index++;
setCurrentItem(index);
//通过重复发送消息达到无限轮播
Message message = Message.obtain();
message.what = 1;
mHandler.sendMessageDelayed(message,delayMislls);
}
}
};
public void setAutoScroll(boolean autoScroll) {
isAutoScroll = autoScroll;
}
//开始轮播
public void startScroll(){
Message message = Message.obtain();
message.what = 1;
mHandler.sendMessageDelayed(message,delayMislls);
}
//停止轮播,清空消息
public void stopScroll(){
mHandler.removeCallbacksAndMessages(null);
}
而我们的触摸监听器也需修改
/**
* 页面触摸监听器
*/
class MyOnTouchListener implements OnTouchListener{
int downx;
long downTime;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
downx = (int) getX();
downTime = System.currentTimeMillis();
if (isAutoScroll){
stopScroll();
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
int upx = (int) getX();
if (downx==upx && System.currentTimeMillis() - downTime<300){
if (itemClickListener!=null){
itemClickListener.itemClickListener(currentPage%pageCount);
}
}
if (isAutoScroll){
startScroll();
}
break;
case MotionEvent.ACTION_CANCEL:
if (isAutoScroll){
startScroll();
}
break;
}
return true;
}
}
最后在MainActivity中使用
autoScrollViewPager.setAutoScroll(true);
效果如下
完整代码
public class AutoScrollViewPager extends ViewPager{
private List<String> imgUrl;//图片地址
private List<ImageView> imageViews = new ArrayList<>();//指示器控件集合
private List<String> titles;
private TextView textView;
private ImageLoadCache imageLoadCache;
private int pageCount;//总页数
private int currentPage;//当前页
private boolean isLooping = false;//是否启用自动轮播,默认为false
private OnItemClickListener itemClickListener;
private int delayMislls = 3000;//默认间隔3秒
private boolean isAutoScroll = false;//默认不开启自动轮播
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (msg.what==1){
int index = getCurrentItem();
index++;
setCurrentItem(index);
Message message = Message.obtain();
message.what = 1;
mHandler.sendMessageDelayed(message,delayMislls);
}
}
};
public void setAutoScroll(boolean autoScroll) {
isAutoScroll = autoScroll;
}
public interface OnItemClickListener{
void itemClickListener(int postion);
}
public void setItemClickListener(OnItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
public void setLooping(boolean looping) {
isLooping = looping;
}
public void setTitles(List<String> titles, TextView textView) {
this.titles = titles;
this.textView = textView;
textView.setText(titles.get(0));//默认设置第一个标题
}
public void setImgUrl(List<String> imgUrl) {
this.imgUrl = imgUrl;
}
public AutoScrollViewPager(Context context) {
super(context);
}
public AutoScrollViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void init(int pageNum,LinearLayout layout){
pageCount = pageNum;//得到总页数
for (int i = 0; i < pageCount; i++) {
ImageView imageView = new ImageView(getContext());
imageView.setBackgroundResource(R.drawable.dot_selector);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
params.rightMargin = 6;//设置指示器之间的距离
imageViews.add(imageView);
layout.addView(imageView,params);
}
imageViews.get(0).setSelected(true);//默认第一个选中
imageLoadCache = new ImageLoadCache(getContext());
this.setAdapter(new MyPagerAdapter());
this.setOnPageChangeListener(new MyPageChangeListener());
if (isAutoScroll){
startScroll();
}
}
public void startScroll(){
Message message = Message.obtain();
message.what = 1;
mHandler.sendMessageDelayed(message,delayMislls);
}
public void stopScroll(){
mHandler.removeCallbacksAndMessages(null);
}
/**
* 页面触摸监听器
*/
class MyOnTouchListener implements OnTouchListener{
int downx;
long downTime;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
downx = (int) getX();
downTime = System.currentTimeMillis();
if (isAutoScroll){
stopScroll();
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
int upx = (int) getX();
if (downx==upx && System.currentTimeMillis() - downTime<300){
if (itemClickListener!=null){
itemClickListener.itemClickListener(currentPage%pageCount);
}
}
if (isAutoScroll){
startScroll();
}
break;
case MotionEvent.ACTION_CANCEL:
if (isAutoScroll){
startScroll();
}
break;
}
return true;
}
}
/**
* 页面切换监听器
*/
class MyPageChangeListener implements OnPageChangeListener{
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
//修改上一个的状态
imageViews.get(currentPage%pageCount).setSelected(false);
//更新新的未位置
currentPage = position;
//修改当前位置指示器的状态
imageViews.get(currentPage%pageCount).setSelected(true);
if (titles!=null && textView!=null){
textView.setText(titles.get(position%pageCount));
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
/**
* ViewPager的适配器
*/
class MyPagerAdapter extends PagerAdapter{
@Override
public int getCount() {
if (isLooping){
return Integer.MAX_VALUE;//如果启动无限轮播,则返回int的最大值
}else {
return imgUrl.size();
}
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(getContext());
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);//设置图片显示样式
//设置布局参数
ViewPager.LayoutParams params = new LayoutParams();
params.width = ViewPager.LayoutParams.MATCH_PARENT;
params.height = ViewPager.LayoutParams.MATCH_PARENT;
//加载图片
//对postion做取余操作,让下标不越界
imageLoadCache.displayImage(imageView,imgUrl.get(position%pageCount));
//将imageView加入到容器中
container.addView(imageView,params);
imageView.setOnTouchListener(new MyOnTouchListener());
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//将ImageView从容器中移除
container.removeView((View) object);
}
}
}
项目中使用
好了这项自定义轮播条已经完成,在项目中使用下吧
结尾
项目已传致Github,看完有收获的小伙伴们点下star吧
Github链接