
首先明确需求:
看一下我画的设计结构图(很丑,轻拍)
可以看到有这么几个对象:
ImageBanner:自定义控件,包含定时任务管理器TimerController、增强ViewPager、指示器BannerIndicator。内部包含了诸如开启,关闭轮播等逻辑。设计为抽象类,通过钩子方法实现UI样式的自定义。
TimerController: 定时任务管理器, 无论是Timer也好,手动设计的定时Handler也好,它的职责就是执行定时任务,具体到图片轮播器里,职责就通知CirclePageAdapter和BannerIndicator切换到下一张。
CustomSwipeViewPager: 增强ViewPager, 方便随时禁止和开启手势滑动。
CirclePageAdapter: ViewPager的adapter, 通过在左右两边各增加一个伪Pager,滑动到0,和最后一个时,无动画切换到最后一个和0,从而实现循环滑动。同样设计为抽象类,ImageView的样式,图片加载的方式等同样通过钩子方法留出来供使用者自定义。
BannerIndicator: 指示器,设计成接口形式,实现该接口的自定义View都可以作为轮播器当中的指示器。最大程度自定义UI。
如何使用?
派生CirclePageAdapter,实现单个图片加载的样式和点击事件
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class CustomCirclePageAdapter extends CirclePageAdapter<bannerimage> { public CustomCirclePageAdapter(Context context) { super(context); } @Override protected void showImage(ImageView vImage, BannerImage bannerImage) { //自定义采用何种图片加载方式 Glide.with(mContext) .load(bannerImage.getImagePath()) .placeholder(R.drawable.default_loading) .error(R.drawable.topic_pic) .dontAnimate() .into(vImage); } @Override protected void onClickImage(final BannerImage bannerImage) { //自定义每张图片的点击事件 Uri uri = Uri.parse(bannerImage.getLink()); Intent intent = new Intent(Intent.ACTION_VIEW, uri); try { mContext.startActivity(intent); } catch (Exception e) { e.printStackTrace(); } } @Override protected ImageView createImageView() { //自定义图片的样式 ImageView vImage = new ImageView(mContext); vImage.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, DemoUtil.dp2px(mContext, 100))); vImage.setScaleType(ImageView.ScaleType.FIT_XY); return vImage; }}</bannerimage> |
自定义指示器(可选),实现BannerIndicator接口即可
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public class CustomBannerIndicator extends LinearLayout implements BannerIndicator { private List<imageview> vimg = new ArrayList<>(); public CustomBannerIndicator(Context context) { this(context, null); } public CustomBannerIndicator(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomBannerIndicator(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { setOrientation(HORIZONTAL); } @Override public void showInitState(int imageCount) { for (int i = 0; i < imageCount; i++) { ImageView vImage = new ImageView(getContext()); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); int margin = DemoUtil.dp2px(getContext(), 10); layoutParams.setMargins(margin, 0, margin, 0); vImage.setLayoutParams(layoutParams); vimg.add(vImage); vImage.setBackgroundResource(i == 0 ? R.drawable.dot_choosen_ic : R.drawable.dot_unchoosen_ic); addView(vImage); } } @Override public void notifyIndexChanged(int indexOfImage) { for (int i = 0; i < vimg.size(); i++) { vimg.get(i).setBackgroundResource(i == indexOfImage ? R.drawable.dot_choosen_ic : R.drawable.dot_unchoosen_ic); } }}</imageview> |
配置ImageBanner
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
public class CustomImageBanner extends ImageBanner<bannerimage> { public CustomImageBanner(Context context) { super(context); } public CustomImageBanner(Context context, AttributeSet attrs) { super(context, attrs); } public CustomImageBanner(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected int getLayoutRes() { return R.layout.custom_banner; } @Override protected int getImagePagerViewId() { return R.id.image_parer; } @Override protected CirclePageAdapter<bannerimage> initCirclePageAdapter() { return new CustomCirclePageAdapter(getContext()); } @Override protected int getBannerIndicatorViewId() { return R.id.image_indicator; }}</bannerimage></bannerimage> |
在xml中使用:
|
1
2
3
4
5
|
<com.tianyeguang.imagebanner.banner.CustomImageBanner android:id="@+id/custom_image_banner" android:layout_width="match_parent" android:layout_height="136dp" android:layout_margin="16dp"/> |
传入数据,正确的开启和关闭轮播的定时器:
|
01
02
03
04
05
06
07
08
09
10
|
@Overrideprotected void onResume() { super.onResume(); vBanner.start();}@Overrideprotected void onPause() { vBanner.finish(); super.onPause();} |
具体的代码大家可以查看demo, demo的样式就是博文上的示意图,谢谢大家的阅读~