实现思路就是通过viewPager自定义组件,支持图片点击、手动滑动、自动轮播、初始化定位位置。不废话了先上图
组件使用
public class BannerAutoActivity extends Activity {
BannerLayout bannerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner_auto);
initView();
}
private void initView(){
//界面初始化view
bannerLayout = (BannerLayout) findViewById(R.id.bannerLayout);
//组织界面图片数据
List<ImageView> ivList = new ArrayList<>();
for(int i=0;i<6;i++){
ImageView imageView = new ImageView(this);
ViewGroup.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
imageView.setLayoutParams(layoutParams);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
imageView.setImageResource(R.mipmap.banner_01+i);
ivList.add(imageView);
}
//设置初始展示第几张
// bannerLayout.setIdx(0);
bannerLayout.startBanner(ivList,R.drawable.point_background);
//图片点击事件监听
bannerLayout.setonClickImg(new BannerLayout.onClickImg() {
@Override
public void ItemId(int id) {
int temp = id+1;
Toast.makeText(BannerAutoActivity.this,"这是第"+temp+"张图",Toast.LENGTH_SHORT).show();
}
});
}
}
到此通过组件就可以实现上图的效果了。继续向下看,自定义view内部的内容。
自定义View一共用了三个文件。
Banners.java
ChildViewPager.java
BannerLayout.java
实体类
Banners.java
public class Banners {
private String picurl;
private String url;
private String name;
public void setPicurl(String picurl) {
this.picurl = picurl;
}
public String getPicurl() {
return this.picurl;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrl() {
return this.url;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
自定义viewPager
ChildViewPager.java
主要重写 onTouchEvent(),实现点击监听和解决滑动冲突问题。因为在项目中当前界面为ScrollView,所以有滑动冲突问题。
@Override
public boolean onTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
//每次进行onTouch事件都记录当前的按下的坐标
curP.x = arg0.getX();
curP.y = arg0.getY();
if(arg0.getAction() == MotionEvent.ACTION_DOWN){
//记录按下时候的坐标
//切记不可用 downP = curP ,这样在改变curP的时候,downP也会改变
downP.x = arg0.getX();
downP.y = arg0.getY();
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
getParent().requestDisallowInterceptTouchEvent(true);
}
if(arg0.getAction() == MotionEvent.ACTION_MOVE){
//此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
getParent().requestDisallowInterceptTouchEvent(true);
}
if(arg0.getAction() == MotionEvent.ACTION_UP){
//在up时判断是否按下和松手的坐标为一个点 这里可以把判断放松一点
//如果是一个点,将执行点击事件,这是我自己写的点击事件,而不是onclick
if(downP.x==curP.x && downP.y==curP.y){
onSingleTouch();
return true;
}
// return super.onTouchEvent(arg0);
}
return super.onTouchEvent(arg0);
}
/**
* 单击
*/
public void onSingleTouch() {
if (onSingleTouchListener!= null) {
onSingleTouchListener.onSingleTouch();
}
}
重头戏来啦
BannerLayout.java
首先是初始化函数
这里就能看到使用中的影子了,设置数据public BannerLayout(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; LayoutInflater.from(context).inflate(R.layout.viewpager_banner, this); setUpView(); } private void setUpView() { mViewPager = (ChildViewPager) findViewById(R.id.viewpager); llPoints = (LinearLayout) findViewById(R.id.ll_points); mViewPager.setOnSingleTouchListener(new ChildViewPager.OnSingleTouchListener() { @Override public void onSingleTouch() { // TODO Auto-generated method stub onClickImg.ItemId(currentId%ivList.size()); } }); ivList = new ArrayList<>(); llPoints.removeAllViews(); }
/**
* @param dotId 圆点资源id
* @param ivList 参数的size必需相等,不然报错
*/
public void startBanner(List<ImageView> ivList, int dotId) {
this.ivList = ivList;
for (int i = 0; i < ivList.size(); i++) {
view = new View(context);
view.setBackgroundDrawable(getResources()
.getDrawable(dotId));
initPoint(view, pointSmall);
view.setEnabled(false);
llPoints.addView(view);
}
initDataImg();
}
/**
* 设置数据
*/
private void initDataImg() {
ViewPagerAdapter adapter = new ViewPagerAdapter();
mViewPager.setAdapter(adapter);
mViewPager.setOnPageChangeListener(this);
llPoints.getChildAt(0).setEnabled(true);
initPoint(llPoints.getChildAt(0), pointBig);
mViewPager.setCurrentItem(idx);
imgHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
}
这些都是viewPager的惯用方法。下边说说自动轮播的实现。
自动轮播通过handle队列机制呼叫实现,handle设置如下
/**
* 请求更新显示的View。
*/
protected static final int MSG_UPDATE_IMAGE = 1;
/**
* 请求暂停轮播。
*/
protected static final int MSG_KEEP_SILENT = 2;
/**
* 请求恢复轮播。
*/
protected static final int MSG_BREAK_SILENT = 3;
/**
* 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页,
* 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。
*/
protected static final int MSG_PAGE_CHANGED = 4;
// 轮播间隔时间
protected static long MSG_DELAY = 3000;
private Handler imgHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
// 检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
if (imgHandler.hasMessages(MSG_UPDATE_IMAGE)) {
imgHandler.removeMessages(MSG_UPDATE_IMAGE);
}
switch (msg.what) {
case MSG_UPDATE_IMAGE:
mViewPager.setCurrentItem(currentId + 1);
// 准备下次播放
sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_KEEP_SILENT:
// 只要不发送消息就暂停了
break;
case MSG_BREAK_SILENT:
sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
case MSG_PAGE_CHANGED:
// 记录当前的页号,避免播放的时候页面显示不正确。
// currentIcon = msg.arg1;
break;
default:
break;
}
}
};
在viewPage r的监听器onPageScrollStateChanged中我们 可以使用handle中的方法达到想要的效果
@Override
public void onPageScrollStateChanged(int arg0) {
// Auto-generated method stub
switch (arg0) {
case ViewPager.SCROLL_STATE_DRAGGING:
imgHandler.sendEmptyMessage(MSG_KEEP_SILENT);
break;
case ViewPager.SCROLL_STATE_IDLE:
imgHandler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
break;
default:
break;
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// 切换选中的点
llPoints.getChildAt(previousSelectPosition).setEnabled(false); // 把前一个点置为normal状态
initPoint(llPoints.getChildAt(previousSelectPosition), pointSmall);
llPoints.getChildAt(position % ivList.size()).setEnabled(true); // 把当前选中的position对应的点置为enabled状态
initPoint(llPoints.getChildAt(position % ivList.size()), pointBig);
previousSelectPosition = position % ivList.size();
currentId = position;
imgHandler.sendMessage(Message.obtain(imgHandler, MSG_PAGE_CHANGED,
position, 0));
}