轮播图控件刚毕业的同学们就会写了,这里简单介绍下自己在做RN轮播图时一些心得:
- 回收与复用弃用的子view,至多只会存在有3个子View的实例。
- 手动滑动与自动播放的优雅处理,不重写onTouchEvent。
- 使用fresco的SimpleDraweeView作为子View加载网络图片,管理图片缓存
- 循环轮播,播放到最后一张图时,下一张为第一张图
1. 回收与复用弃用的子view
申明一个list来存储弃用的子view。2. 手动滑动与自动播放的优雅处理
一般轮播图都支持手动滑动,在手动滑动式是应当禁止自动播放的,我发现同学们第一想到的解决方案是复写view的onTouchEvent()方法,在ACTION_DOWN时禁止自动播放,在ACTION_UP时恢复自动播放,当然这个方案无可厚非,只不过可能需要考虑touchEvent的各种事件而不仅仅是down和up,且是否要消费touch事件很多人处理的不一样,我介绍下另一种通过处理OnPageChangeListener中的onPageScrollStateChanged()方法来实现该功能的方法3. 使用fresco的SimpleDraweeView作为子View
呃,fresco的SimpleDraweeView继承与ImageView,可以帮助我们处理下载网络图片的功能,还可以自动管理图片缓存,是一个非常棒的网络图像控件,推荐给大家,具体用法在图3中。另外在使用SimpleDraweeView前,一定不要忘记了调用4. 循环轮播
相信这个功能的实现同学们的都耳熟能详,我和大家并无二样,一来凑个数,二来方便新人了解
然后就没有了
完整代码如下
public class TurnPlayer extends FrameLayout implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private String[] mUrls;
private List<SimpleDraweeView> unusedList = new ArrayList<>();
private int delay = 2000; // 默认轮播时间
final Runnable runnable = new Runnable() {
@Override
public void run() {
if (getContext() != null) {
int currentItem = mViewPager.getCurrentItem();
mViewPager.setCurrentItem(currentItem + 1, true);
postDelayed(runnable, delay);
}
}
};
public TurnPlayer(@NonNull Context context) {
super(context);
init(context);
}
public TurnPlayer(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public TurnPlayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mViewPager = new ViewPager(context);
mViewPager.setAdapter(new TurnPlayerAdapter());
mViewPager.addOnPageChangeListener(this);
addView(mViewPager);
Fresco.initialize(context);
}
void setDelay(int delay) {
this.delay = delay;
}
void setData(String... urls) {
mUrls = urls;
mViewPager.getAdapter().notifyDataSetChanged();
postDelayed(runnable, delay);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
postDelayed(runnable, delay);//恢复自动播放
} else {
removeCallbacks(runnable);//禁止自动播放
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
postDelayed(runnable, delay);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(runnable);
}
private class TurnPlayerAdapter extends PagerAdapter {
@Override
public int getCount() {
return mUrls == null ? 0 : (mUrls.length > 1 ? Integer.MAX_VALUE : mUrls.length);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return object == view;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
SimpleDraweeView view;
if (unusedList.isEmpty()) {
view = new SimpleDraweeView(container.getContext());
view.getHierarchy().setActualImageScaleType(ScalingUtils.ScaleType.CENTER_INSIDE);
} else {
view = unusedList.remove(0);
}
view.setController(Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(mUrls[position % mUrls.length]))
.setAutoPlayAnimations(true)
.build());
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
unusedList.add((SimpleDraweeView) object);
}
}
}