android 图片轮播(自动循环轮播)
16lz
2021-01-25
实现思路就是通过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 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 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)); }
组件下载
更多相关文章
- Fresco对Eclipse的支持以及使用教程
- Android启动流程简析(三)
- Android一些开源第三方
- 常用的Android(安卓)Widget组件学习②-EditText的介绍和应用。
- android中使用多个CheckBox联动,CheckBox的setOnCheckedChangeLis
- Android通过PendingIntent实现消息通知
- Android(安卓)SparseArray的用法
- Android(安卓)源码环境搭建配置与问题解析(二)
- Bmob SDK导入和初始化