Android TV填坑之旅(二)--VIEWPAGER的使用(包括循环播放)

本文探讨了在Android中使用VIEWPAGER实现幻灯片效果的挑战与解决方案,特别是循环播放的问题。介绍了如何通过修改PagerAdapter并利用开源库LoopingViewPager来实现平滑过渡,同时讨论了实现过程中的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当Android中想呈现幻灯片效果时,会想到使用VIEWPAGER加载图片呈现出来,实际操作的过程中坑无数,这里记录一下。

首先是按键的区别。

在手机中是通过手势监听滑动时间,在电视中是通过遥控器进行。比如说我正在幻灯片播放的时候,按一下前进键,应该停止正在播放。

那么我就需要在ACTIVITY/FRAGMENT层监听按键,而不能将按键事件传递给VIEWPAGER,这样事件就才能被ACTIVITY监听。

两个方案:

1.设置VIEWPAGER取不到焦点。

2.设置dispatchTouchEvent.阻断按键下行。

我实际采取了方案1,因为代码简单~~


循环播放的解决

其实最终的结论是目前看没有完美的解决方案。

先说MAX_INT的解决方案,问题很多,如果需要比较好的执行,需要先预制所有VIEW。。。当你照片多的时候,你懂得。。。

这个方案也可以不预置VIEW,但是当setCurrentItem的时候,会出现ANR。所以该方案PASS。


来看下面的规避方案,也是我现在做的方案。


先来介绍一下借用的开源库:

https://github.com/imbryk/LoopingViewPager


基础原理:

If you want to use LoopViewPager with FragmentPagerAdapter or FragmentStatePagerAdapter additional changes in the adapter must be done.
The adapter must be prepared to create 2 extra items e.g.:

  • The original adapter creates 4 items: [0,1,2,3]
  • The modified adapter will have to create 6 items [0,1,2,3,4,5]
  • with mapping realPosition=(position-1)%count
  • [0->3, 1->0, 2->1, 3->2, 4->3, 5->0]

自己开始的时候也按照这个思路,但是实际跳转的各种跳变。看了一下源码的实现,差别主要在:

@Override
public Object instantiateItem(ViewGroup container, int position) {
    int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)
            ? position
            : toRealPosition(position);
    Log.e("LoopPagerAdapter", "init position=" + position + "realposition=" + realPosition);
    if (mBoundaryCaching) {
        ToDestroy toDestroy = mToDestroy.get(position);
        if (toDestroy != null) {
            mToDestroy.remove(position);
            return toDestroy.object;
        }
    }
    return mAdapter.instantiateItem(container, realPosition);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    int realFirst = getRealFirstPosition();
    int realLast = getRealLastPosition();
    int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)
            ? position
            : toRealPosition(position);

    Log.e("LoopPagerAdapter", "destroy position=" + position + "realposition=" + realPosition);
    if (mBoundaryCaching && (position == realFirst || position == realLast)) {
        mToDestroy.put(position, new ToDestroy(container, realPosition,
                object));
    } else {
        mAdapter.destroyItem(container, realPosition, object);
    }
}

区别就在红色的字体处,边界会进行缓存。。。

实际使用的时候还是有坑的:
1.快速滑动的时候,过边界的时候,还是可能会跳变。(这个没有办法解决,按键比手划快多了,手划出现的概率应该更小)
2.如果加入滑动动画,开始的时候从第一个往前滚到最后一个,会出现空图,viewpager不会预加载最后一张图。
  这个时候缓存也没有生成。想了个规避办法,那就是滑到最后一个,就直接切到最后1个去,不切到-1(对应LoopViewPager 0)位置上去。。。

现在的实现效果就是自动播放可以完美运行,手动左滑到边界会跳一下,右滑快速滑动可能跳变。
目前就这样了,如果还有更好的解决方案欢迎提建议。	


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值