接着上一篇MonkeyLei:更全的ViewPager2的使用方式总结, Glide加载https空白问题(http也要修改配置) 我们继续完善这个Banner。让其更像一个轮播组件。目前模块已经添加到https://github.com/FanChael/MVVM 下面, lib_banner模块。
- 继承ViewGroup,为了增加Banner圆角,自行测量和布局,主要是为了将addView进来 的Viewpaper2设置一个margin,让其内容在边框里面,不超区边框,然后实现上层绘制覆盖一个圆角的效果重写dispatchDraw,这里做最后的绘制.
- 搞定了边框绘制,指示器绘制相对容易一些:解决下绘制的位置,然后判断当前是第几个页面,此时指示器颜色有所区别,然后当滚动一定距离,绘制贪吃蛇效果,当滚动到下一个位置,刷新指示器颜色效果 - 重点是ViewPager2.OnPageChangeCallback回调的监听以及相关位置的计算判断 建议打印如下日志去分析,如何实现圆点贪吃蛇和切换:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
this.current_pos = position;
this.positionOffset = positionOffset;
viewGroup.invalidate();
}
由于无线轮播,所以计算当前位置需要current_pos % count,另外上面回调里面的positionOffset整好是一个百分比小数,整好做贪吃蛇宽度的百分比,实现贪吃蛇效果。。
for (int i = 0; i < count; ++i) {
int last_pos = current_pos % count;
// 画贪吃蛇
if (last_pos < (count - 1)) {
if (positionOffset >= 0.0000001) {
canvas.drawLine(
leftX + last_pos * (dot_space + dot_radius * 2),
topY, leftX + last_pos * (dot_space + dot_radius * 2) + (dot_space + dot_radius * 2) * positionOffset,
topY, snakePaint);
}
}
// 画原点
if (i == last_pos) {
dotPaint.setColor(dot_selected_color);
} else {
dotPaint.setColor(dot_color);
}
canvas.drawCircle(
leftX + (dot_space + dot_radius * 2) * i,
topY,
dot_radius, dotPaint);
}
- 当Touch down的时候,停止轮播,Viewpaper2已经提供回调onPageScrollStateChanged处理 - 注意外部setTouchEvent事件是无效的。。另外ViewPaper2不能继承,所以不能像Viewpaper那样重写DispatchEvent事件来处理哟。
@Override
public void onPageScrollStateChanged(int state) {
// 返回Down和UP事件回调
if (null != mOnTouchListener) {
if (ViewPager2.SCROLL_STATE_DRAGGING == state) {
mOnTouchListener.onTouch(MotionEvent.ACTION_DOWN);
} else if (ViewPager2.SCROLL_STATE_IDLE == state) {
mOnTouchListener.onTouch(MotionEvent.ACTION_UP);
}
}
}
综上一系列构想和实现,以及完善过程遇到的问题,目前基本都解决了。。效果也还好,不差,至少满足了项目需求。。 你可以扩展为自己的组件库。。或者搞得更好,开源一把。。最近忙准备面试,所以就不搞了。。。各位大佬,共勉。。。。到目前我的MVVM工程已经自定义了两个组件,一个刷新,一个轮播,刷新目前还有些问题。。。后续完善。。。除了备战,将会继续完善简化这个工程模板。 供参考学习...