当前位置:首页 > 黑客业务 > 正文内容

抖音文案怎么取消滚动,抖音视频滚动评论如何关闭

访客3年前 (2021-11-08)黑客业务918

  0、效果图

  

  

  

  

  

  

  

  

  1、先来看一下需求

  

  

  1\.

  

  

  项目中的视频回放要求Tik Tok在垂直方向上一次滑动一页。滑动要平稳不卡,手动触摸滑动超过1/2时松开即可滑动下一页,不超过1/2即可返回原页面。

  

  

  2\.手指拖动页面滑动,只要不切换到其他页面,视频就在播放。切换页面时,之前的视频被破坏,页面开始初始化播放。

  

  

  3\.切换页面时,过渡效果要自然,避免屏幕闪烁。具体滑动效果请直接参考Tik Tok….

  

  

  公开来源地址:.

  

  

  _ https://github.com/yang chong 211/ycscroll pager _

  

  

  2、有几种实现方式

  

  

  2.1 使用ViewPager

  

  

  使用ViewPager实现竖直方法上下切换视频分析

  

  

  1.最近需要在ViewPager中播放视频,也就是上下垂直滑动切换视频,视频就是网络视频。最初的实现思路是根据ViewPager中当前的项目位置初始化SurfaceView,销毁时根据项目位置移除SurfaceView。

  

  

  2.上面的方法可以实现,但是有两个问题。第一,MediaPlayer的生命周期不易控制,存在内存泄漏问题。第二,当连续三个项目都是视频时,发现最后一个视频的最后一帧的bug会在来回滑动的过程中出现。

  

  

  3.用户体验没有得到改善。在视频播放器初始化完成之前,视频的第一帧画面会被覆盖在上面。但是发现第一帧图片与视频的第一帧信息不一致,后面会通过代码给出解决方案。

  

  

  大概的实现思路是这样   

  

  1.有必要定制一个在垂直方向滑动的可视寻呼机。注意这一点尤为重要。

  

  

  2.一次滑动一页,建议使用查看寻呼机片段状态寻呼机适配器片段,这将在后面详细描述。

  

  

  3.在片段中处理视频初始化、回放和销毁的逻辑。

  

  

  4.由于一个页面需要创建一个片段,所以要注意性能和滑动流畅度,这需要分析和讨论。

  

  

  不太建议使用ViewPager

  

  

  1.1的滑动效果。ViewPager完全符合场景,支持片段、视图等UI绑定。只要修改布局和触摸事件,水平就可以改变。

  

  

  视图寻呼机更改为垂直。

  

  

  2.但是没有复用才是最致命的问题。在onLayout方法中,所有子视图都被实例化并排列在布局上。当项目数量很大时,将会极大地浪费性能。

  

  

  3.其次,可见性判断的问题。许多人会认为片段在电子邮件上是可见的,但是片段在可视寻呼机上。

  

  

  是一个反例,尤其是当多个ViewPager嵌套时,onresume中同时存在多个父片段和多个子片段。

  

  

  状态,但只能看到其中一个。

  

  

  除非放弃ViewPager的预加载机制。当报告页面内容曝光等重要数据时,需要判断许多条件:在电子邮件上,.

  

  

  SetUserVisibleHint、setOnPageChangeListener等。

  

  

  2.2 使用RecyclerView

  

使用RecyclerView实现树枝方向上下切换视频分析   

1.首先RecyclerView它设置竖直方向滑动是十分简单的,同时关于item的四级缓存也做好了处理,而且滑动的效果相比ViewPager要好一些。   

2.滑动事件处理比viewPager好,即使你外层嵌套了下拉刷新上拉加载的布局,也不影响后期事件冲突处理,详细可以看demo案例。   

大概的实现思路是这样   

1.自定义一个LinearLayoutManager,重写onScrollStateChanged方法,注意是拿到滑动状态。   

2.一次滑动切换一个页面,可以使用PagerSnapHelper来实现,十分方便简单。   

3.在recyclerView对应的adapter中,在onCreateViewHolder初始化视频操作,同时当onViewRecycled时,销毁视频资源。   

4.添加自定义回调接口,在滚动页面和attch,detach的时候,定义初始化,页面销毁等方法,暴露给开发者。   

3、用ViewPager实现   

3.1 自定义ViewPager   

代码如下所示,这里省略了不少的代码,具体可以看项目中的代码。   

/ *

* @author 杨充 * blog : https://github.com/yangchong211 * time : 2019/6/20 * desc : 自定义ViewPager,主要是处理边界极端情况 * revise: * */public class VerticalViewPager extends ViewPager { private boolean isVertical = false; private long mRecentTouchTime; public VerticalViewPager(@NonNull Context context) { super(context); } public VerticalViewPager(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } private void init() { setPageTransformer(true, new HorizontalVerticalPageTransformer()); setOverScrollMode(OVER_SCROLL_NEVER); } public boolean isVertical() { return isVertical; } public void setVertical(boolean vertical) { isVertical = vertical; init(); } private class HorizontalVerticalPageTransformer implements PageTransformer { private static final float MIN_SCALE = 0.25f; @Override public void transformPage(@NonNull View page, float position) { if (isVertical) { if (position < -1) { page.setAlpha(0); } else if (position <= 1) { page.setAlpha(1); // Counteract the default slide transition float xPosition = page.getWidth() * -position; page.setTranslationX(xPosition); //set Y position to swipe in from top float yPosition = position * page.getHeight(); page.setTranslationY(yPosition); } else { page.setAlpha(0); } } else { int pageWidth = page.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. page.setAlpha(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page page.setAlpha(1); page.setTranslationX(0); page.setScaleX(1); page.setScaleY(1); } else if (position <= 1) { // (0,1] // Fade the page out. page.setAlpha(1 - position); // Counteract the default slide transition page.setTranslationX(pageWidth * -position); page.setTranslationY(0); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); page.setScaleX(scaleFactor); page.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. page.setAlpha(0); } } } } /

* 交换x轴和y轴的移动距离 * @param event 获取事件类型的封装类MotionEvent */ private MotionEvent swapXY(MotionEvent event) { //获取宽高 float width = getWidth(); float height = getHeight(); //将Y轴的移动距离转变成X轴的移动距离 float swappedX = (event.getY() / height) * width; //将X轴的移动距离转变成Y轴的移动距离 float swappedY = (event.getX() / width) * height; //重设event的位置 event.setLocation(swappedX, swappedY); return event; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { mRecentTouchTime = System.currentTimeMillis(); if (getCurrentItem() == 0 && getChildCount() == 0) { return false; } if (isVertical) { boolean intercepted = super.onInterceptTouchEvent(swapXY(ev)); swapXY(ev); // return touch coordinates to original reference frame for any child views return intercepted; } else { return super.onInterceptTouchEvent(ev); } } @Override public boolean onTouchEvent(MotionEvent ev) { if (getCurrentItem() == 0 && getChildCount() == 0) { return false; } if (isVertical) { return super.onTouchEvent(swapXY(ev)); } else { return super.onTouchEvent(ev); } }}   

3.2 ViewPager和Fragment   

采用了ViewPager+FragmentStatePagerAdapter+Fragment来处理。为何选择使用FragmentStatePagerAdapter,主要是因为使用   

FragmentStatePagerAdapter更省内存,但是销毁后新建也是需要时间的。   

一般情况下,如果你是用于ViewPager展示数量特别多的条目时,那么建议使用FragmentStatePagerAdapter。关于PagerAdapter的深度解析,可以我这篇文章:   

PagerAdapter深度解析和实践优化   

_https://juejin.im/post/5d401cabf265da03a53a12fe_   

在activity中的代码如下所示   

private void initViewPager() { List list = new ArrayList<>(); ArrayList fragments = new ArrayList<>(); for (int a = 0; a< DataProvider.VideoPlayerList.length ; a++){ Video video = new Video(DataProvider.VideoPlayerTitle[a], 10,"",DataProvider.VideoPlayerList[a]); list.add(video); fragments.add(VideoFragment.newInstant(DataProvider.VideoPlayerList[a])); } vp.setOffscreenPageLimit(1); vp.setCurrentItem(0); vp.setOrientation(DirectionalViewPager.VERTICAL); FragmentManager supportFragmentManager = getSupportFragmentManager(); MyPagerAdapter myPagerAdapter = new MyPagerAdapter(fragments, supportFragmentManager); vp.setAdapter(myPagerAdapter);}class MyPagerAdapter extends FragmentStatePagerAdapter{ private ArrayList list; public MyPagerAdapter(ArrayList list , FragmentManager fm){ super(fm); this.list = list; } @Override public Fragment getItem(int i) { return list.get(i); } @Override public int getCount() { return list!=null ? list.size() : 0; }}   

那么在fragment中如何处理呢?   

关于视频播放器,这里可以看我封装的库,视频libpublic   

_https://github.com/yangchong211/YCVideoPlayer_   

public class VideoFragment extends Fragment{ public VideoPlayer videoPlayer; private String url; private int index; @Override public void onStop() { super.onStop(); VideoPlayerManager.instance().releaseVideoPlayer(); } public static Fragment newInstant(String url){ VideoFragment videoFragment = new VideoFragment(); Bundle bundle = new Bundle(); bundle.putString("url",url); videoFragment.setArguments(bundle); return videoFragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle arguments = getArguments(); if (arguments != null) { url = arguments.getString("url"); } } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_video, container, false); return view; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); videoPlayer = view.findViewById(R.id.video_player); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.d("初始化操作","------"+index++); VideoPlayerController controller = new VideoPlayerController(getActivity()); videoPlayer.setUp(url,null); videoPlayer.setPlayerType(ConstantKeys.IjkPlayerType.TYPE_IJK); videoPlayer.setController(controller); ImageUtils.loadImgByPicasso(getActivity(),"", R.drawable.image_default,controller.imageView()); }}   

3.3 修改滑动距离翻页   

需求要求必须手动触摸滑动超过1/2的时候松开可以滑动下一页,没有超过1/2返回原页,首先肯定是重写viewpager,只能从源码下手。经过分析,源码滑动的逻辑处理在此处,truncator的属性代表判断的比例值!   

这个方法会在切页的时候重定向Page,比如从第一个页面滑动,结果没有滑动到第二个页面,而是又返回到第一个页面,那个这个page会有重定向的功能   

private int determineTargetPage(int currentPage, float pageOffset, int velocity, int deltaX) { int targetPage; if (Math.abs(deltaX) > this.mFlingDistance && Math.abs(velocity) > this.mMinimumVelocity) { targetPage = velocity > 0 ? currentPage : currentPage + 1; } else { float truncator = currentPage >= this.mCurItem ? 0.4F : 0.6F; targetPage = currentPage + (int)(pageOffset + truncator); } if (this.mItems.size() > 0) { ViewPager.ItemInfo firstItem = (ViewPager.ItemInfo)this.mItems.get(0); ViewPager.ItemInfo lastItem = (ViewPager.ItemInfo)this.mItems.get(this.mItems.size() - 1); targetPage = Math.max(firstItem.position, Math.min(targetPage, lastItem.position)); } return targetPage;}   

determineTargetPage这个方法就是计算接下来要滑到哪一页。这个方法调用是在MotionEvent.ACTION_UP这个事件下,先说下参数意思:   

* currentPage:当前ViewPager显示的页面   

* pageOffset:用户滑动的页面偏移量   

* velocity: 滑动速率   

* deltaX: X方向移动的距离   

进行debug调试之后,发现问题就在0.4f和0.6f这个参数上。分析得出:0.6f表示用户滑动能够翻页的偏移量,所以不难理解,为啥要滑动半屏或者以上了。   

也可以修改Touch事件   

控制ViewPager的Touch事件,这个基本是万能的,毕竟是从根源上入手的。你可以在onTouchEvent和onInterceptTouchEvent中做逻辑的判断。但是比较麻烦。   

3.4 修改滑动速度   

使用viewPager进行滑动时,如果通过手指滑动来进行的话,可以根据手指滑动的距离来实现,但是如果通过setCurrentItem函数来实现的话,则会发现直接闪过去的,会出现一下刷屏。   

想要通过使用setCurrentItem函数来进行viewpager的滑动,并且需要有过度滑动的动画,那么,该如何做呢?   

具体可以分析setCurrentItem源码的逻辑,然后会看到scrollToItem方法,这个特别重要,主要是处理滚动过程中的逻辑。   

最主要关心的也是smoothScrollTo函数,这个函数中,可以看到具体执行滑动的其实就一句话,就是mScroller.startScroll(sx,sy,dx,dy,duration),则可以看到,是mScroller这个对象进行滑动的。那么想要改变它的属性,则可以通过反射来实现。   

代码如下所示,如果是手指触摸滑动,则可以加快一点滑动速率,当然滑动持续时间你可以自己设置。通过自己自定义滑动的时间,就可以控制滑动的速度。   

@TargetApi(Build.VERSION_CODES.KITKAT)public void setAnimationDuration(final int during){ try { // viewPager平移动画事件 Field mField = ViewPager.class.getDeclaredField("mScroller"); mField.setAccessible(true); // 动画效果与ViewPager的一致 Interpolator interpolator = new Interpolator() { @Override public float getInterpolation(float t) { t -= 1.0f; return t * t * t * t * t + 1.0f; } }; Scroller mScroller = new Scroller(getContext(),interpolator){ final int time = 2000; @Override public void startScroll(int x, int y, int dx, int dy, int duration) { // 如果手工滚动,则加速滚动 if (System.currentTimeMillis() - mRecentTouchTime > time) { duration = during; } else { duration /= 2; } super.startScroll(x, y, dx, dy, duration); } @Override public void startScroll(int x, int y, int dx, int dy) { super.startScroll(x, y, dx, dy,during); } }; mField.set(this, mScroller); } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) { e.printStackTrace(); }}   

4、用RecyclerView实现   

4.1 自定义LayoutManager   

  

自定义LayoutManager,并且继承LinearLayoutManager,这样就得到一个可以水平排向或者竖向排向的布局策略。   

如果你接触过SnapHelper应该了解一下LinearSnapHelper和PagerSnapHelper这两个子类类,LinearSnapHelper可以实现让列表的Item居中显示的效果,PagerSnapHelper就可以做到一次滚动一个item显示的效果。   

重写onChildViewAttachedToWindow方法,在RecyclerView中,当Item添加进来了调用这个方法。这个方法相当于是把view添加到window时候调用的,也就是说它比draw方法先执行,可以做一些初始化相关的操作。   

/ * 该方法必须调用 * @param recyclerView */@Overridepublic void onAttachedToWindow(RecyclerView recyclerView) { if (recyclerView == null) { throw new IllegalArgumentException("The attach RecycleView must not null!!"); } super.onAttachedToWindow(recyclerView); this.mRecyclerView = recyclerView; if (mPagerSnapHelper==null){ init(); } mPagerSnapHelper.attachToRecyclerView(mRecyclerView); mRecyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener);}   

4.2 添加滑动监听   

涉及到一次滑动一页视频,那么肯定会有视频初始化和释放的功能。那么思考一下哪里来开始播放视频和在哪里释放视频?   

不要着急,要监听滑动到哪页,需要我们重写onScrollStateChanged()函数,这里面有三种状态:SCROLL_STATE_IDLE(空闲),SCROLL_STATE_DRAGGING(拖动),SCROLL_STATE_SETTLING(要移动到最后位置时)。   

我们需要的就是RecyclerView停止时的状态,我们就可以拿到这个View的Position,注意这里还有一个问题,当你通过这个position去拿Item会报错,这里涉及到RecyclerView的缓存机制,自己去脑补~~。   

打印Log,你会发现RecyclerView.getChildCount()一直为1或者会出现为2的情况。来实现一个接口然后通过接口把状态传递出去。   

自定义监听listener事件   

public interface OnPagerListener { /

* 初始化完成 */ void onInitComplete(); / * 释放的监听 * @param isNext 是否下一个 * @param position 索引 */ void onPageRelease(boolean isNext,int position); /* * 选中的监听以及判断是否滑动到底部 * @param position 索引 * @param isBottom 是否到了底部 */ void onPageSelected(int position,boolean isBottom);}   

获取到RecyclerView空闲时选中的Item,重写LinearLayoutManager的onScrollStateChanged方法:   

/ * 滑动状态的改变 * 缓慢拖拽-> SCROLL_STATE_DRAGGING * 快速滚动-> SCROLL_STATE_SETTLING * 空闲状态-> SCROLL_STATE_IDLE * @param state 状态 */@Overridepublic void onScrollStateChanged(int state) { switch (state) { case RecyclerView.SCROLL_STATE_IDLE: View viewIdle = mPagerSnapHelper.findSnapView(this); int positionIdle = 0; if (viewIdle != null) { positionIdle = getPosition(viewIdle); } if (mOnViewPagerListener != null && getChildCount() == 1) { mOnViewPagerListener.onPageSelected(positionIdle, positionIdle == getItemCount() - 1); } break; case RecyclerView.SCROLL_STATE_DRAGGING: View viewDrag = mPagerSnapHelper.findSnapView(this); if (viewDrag != null) { int positionDrag = getPosition(viewDrag); } break; case RecyclerView.SCROLL_STATE_SETTLING: View viewSettling = mPagerSnapHelper.findSnapView(this); if (viewSettling != null) { int positionSettling = getPosition(viewSettling); } break; default: break; }}   

4.3 监听页面是否滚动   

这里有两个方法scrollHorizontallyBy()和scrollVerticallyBy()可以拿到滑动偏移量,可以判断滑动方向。   

/

* 监听竖直方向的相对偏移量 * @param dy y轴滚动值 * @param recycler recycler * @param state state滚动状态 * @return int值 */@Overridepublic int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { if (getChildCount() == 0 || dy == 0) { return 0; } this.mDrift = dy; return super.scrollVerticallyBy(dy, recycler, state);}/ * 监听水平方向的相对偏移量 * @param dx x轴滚动值 * @param recycler recycler * @param state state滚动状态 * @return int值 */@Overridepublic int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) { if (getChildCount() == 0 || dx == 0) { return 0; } this.mDrift = dx; return super.scrollHorizontallyBy(dx, recycler, state);}   

4.4 attach和Detached   

列表的选中监听好了,我们就看看什么时候释放视频的资源,第二步中的三种状态,去打印getChildCount()的日志,你会发现getChildCount()在SCROLL_STATE_DRAGGING会为   

1\. SCROLL_STATE_SETTLING为2,SCROLL_STATE_IDLE有时为1,有时为   

2\.   

还是RecyclerView的缓存机制O(∩∩)O,这里不会去赘述缓存机制,要做的是要知道在什么时候去做释放视频的操作,还要分清是释放上一页还是下一页。   

private RecyclerView.OnChildAttachStateChangeListener mChildAttachStateChangeListener = new RecyclerView.OnChildAttachStateChangeListener() { /

* 第一次进入界面的监听,可以做初始化方面的操作 * @param view view */ @Override public void onChildViewAttachedToWindow(@NonNull View view) { if (mOnViewPagerListener != null && getChildCount() == 1) { mOnViewPagerListener.onInitComplete(); } } / * 页面销毁的时候调用该方法,可以做销毁方面的操作 * @param view view */ @Override public void onChildViewDetachedFromWindow(@NonNull View view) { if (mDrift >= 0){ if (mOnViewPagerListener != null) { mOnViewPagerListener.onPageRelease(true , getPosition(view)); } }else { if (mOnViewPagerListener != null) { mOnViewPagerListener.onPageRelease(false , getPosition(view)); } } }};   

哪里添加该listener监听事件,如下所示。这里注意需要在页面销毁的时候移除listener监听事件。   

/

* attach到window窗口时,该方法必须调用 * @param recyclerView recyclerView */@Overridepublic void onAttachedToWindow(RecyclerView recyclerView) { //这里省略部分代码 mRecyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener);}/ * 销毁的时候调用该方法,需要移除监听事件 * @param view view * @param recycler recycler */@Overridepublic void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) { super.onDetachedFromWindow(view, recycler); if (mRecyclerView!=null){ mRecyclerView.removeOnChildAttachStateChangeListener(mChildAttachStateChangeListener); }}   

5、优化点详谈   

5.1 ViewPager改变滑动速率   

可以通过反射修改属性,注意,使用反射的时候,建议手动try-catch,避免异常导致崩溃。代码如下所示:   

/ * 修改滑动灵敏度 * @param flingDistance 滑动惯性,默认是75 * @param minimumVelocity 最小滑动值,默认是1200 */public void setScrollFling(int flingDistance , int minimumVelocity){ try { Field mFlingDistance = ViewPager.class.getDeclaredField("mFlingDistance"); mFlingDistance.setAccessible(true); Object o = mFlingDistance.get(this); Log.d("setScrollFling",o.toString()); //默认值75 mFlingDistance.set(this, flingDistance); Field mMinimumVelocity = ViewPager.class.getDeclaredField("mMinimumVelocity"); mMinimumVelocity.setAccessible(true); Object o1 = mMinimumVelocity.get(this); Log.d("setScrollFling",o1.toString()); //默认值1200 mMinimumVelocity.set(this,minimumVelocity); } catch (Exception e){ e.printStackTrace(); }}   

5.2 PagerSnapHelper注意点   

好多时候会抛出一个异常"illegalstateexception an instance of onflinglistener already set".   

看SnapHelper源码attachToRecyclerView(xxx)方法时,可以看到如果recyclerView不为null,则先destoryCallback(),它作用在于取消之前的RecyclerView的监听接口。   

然后通过setupCallbacks()设置监听器,如果当前RecyclerView已经设置了OnFlingListener,会抛出一个状态异常。那么这个如何复现了,很容易,你初始化多次就可以看到这个bug。   

建议手动捕获一下该异常,代码设置如下所示。源码中判断了,如果onFlingListener已经存在的话,再次设置就直接抛出异常,那么这里可以增强一下逻辑判断,ok,那么问题便解决呢!   

try { //attachToRecyclerView源码上的方法可能会抛出IllegalStateException异常,这里手动捕获一下 RecyclerView.OnFlingListener onFlingListener = mRecyclerView.getOnFlingListener(); //源码中判断了,如果onFlingListener已经存在的话,再次设置就直接抛出异常,那么这里可以判断一下 if (onFlingListener==null){ mPagerSnapHelper.attachToRecyclerView(mRecyclerView); }} catch (IllegalStateException e){ e.printStackTrace();}   

5.3 自定义LayoutManager注意点   

网上有人已经写了一篇自定义LayoutManager实现抖音的效果的博客,我自己也很仔细看了这篇文章。不过我觉得有几个注意要点,因为要用到线上app,则一定要尽可能减少崩溃率……   

通过SnapHelper调用findSnapView方法,得到的view,一定要增加非空判断逻辑,否则很容易造成崩溃。   

在监听滚动位移scrollVerticallyBy的时候,注意要增加判断,就是getChildCount()如果为0时,则需要返回0。   

在onDetachedFromWindow调用的时候,可以把listener监听事件给remove掉。   

5.4 视频播放逻辑优化   

从前台切到后台,当视频正在播放或者正在缓冲时,调用方法可以设置暂停视频。销毁页面,释放,内部的播放器被释放掉,同时如果在全屏、小窗口模式下都会退出。   

从后台切换到前台,当视频暂停时或者缓冲暂停时,调用该方法重新开启视频播放。具体视频播放代码设置如下,具体更加详细内容可以看我封装的视频播放器lib:   

_https://github.com/yangchong211/YCVideoPlayer_   

@Overrideprotected void onStop() { super.onStop(); //从前台切到后台,当视频正在播放或者正在缓冲时,调用该方法暂停视频 VideoPlayerManager.instance().suspendVideoPlayer();}@Overrideprotected void onDestroy() { super.onDestroy(); //销毁页面,释放,内部的播放器被释放掉,同时如果在全屏、小窗口模式下都会退出 VideoPlayerManager.instance().releaseVideoPlayer();}@Overridepublic void onBackPressed() { //处理返回键逻辑;如果是全屏,则退出全屏;如果是小窗口,则退出小窗口 if (VideoPlayerManager.instance().onBackPressed()){ return; }else { //销毁页面 VideoPlayerManager.instance().releaseVideoPlayer(); } super.onBackPressed();}@Overrideprotected void onRestart() { super.onRestart(); //从后台切换到前台,当视频暂停时或者缓冲暂停时,调用该方法重新开启视频播放 VideoPlayerManager.instance().resumeVideoPlayer();}   

5.5 视频逻辑充分解藕   

实际开发中,翻页肯定会涉及到视频的初始化和销毁的逻辑。首先要保证视频只有唯一一个播放,滑动到分页一半,总不可能让两个页面都播放视频吧,所以需要保证视频VideoPlayer是一个单利对象,这样就可以保证唯一性呢!   

接着,不管是在recyclerView还是ViewPager中,当页面处于不可见被销毁或者view被回收的阶段,这个时候需要把视频资源销毁,尽量视频播放功能封装起来,然后在页面不同状态调用方法即可。   

当然,实际app中,视频播放页面,还有一些点赞,评论,分享,查看作者等等很多其他功能。那么这些都是要请求接口的,还有滑动分页的功能,当滑动到最后某一页时候拉取下一个视频集合数据等业务逻辑。   

视频播放功能这块,因为功能比较复杂,因此封装一下比较好。尽量做到视频功能解藕!关于视频封装库,可以看我之前写的一个库,视频播放器。   

_https://github.com/yangchong211/YCVideoPlayer_   

5.6 翻页卡顿优化分析   

如果是使用recyclerView实现滑动翻页效果,那么为了提高使用体验效果。则可以注意:   

1.在onBindViewHolder中不要做耗时操作;   

2.视频滑动翻页的布局固定高度,避免重复计算高度RecyclerView.setHasFixedSize(true);   

3.关于分页拉取数据注意,建议一次拉下10条数据(这个也可以和服务端协定自定义数量),而不要滑动一页加载下一页的数据。   

5.7 上拉很快翻页黑屏   

因为设置视频的背景颜色为黑色,我看了好多播放器初始化的时候,都是这样的。因为最简单的解决办法,就是给它加个封面,设置封面的背景即可。

扫描二维码推送至手机访问。

版权声明:本文由黑客接单发布,如需转载请注明出处。

本文链接:http://therlest.com/41626.html

分享给朋友:

“抖音文案怎么取消滚动,抖音视频滚动评论如何关闭” 的相关文章

字节承认商业化团队撤城裁员

据晋江新闻网2021年10月19日21:00:43的最新发布,微博网友@ 爆料。 平安夜来临之际,事件,在网上炒得沸沸扬扬,引发全网热议! 据悉,黑客追款后来被报道了几次。猜测第六百八十八章逃港者第六百八十九章调侃第六百。相对这个账号是他的。 1.专业网赌追回律师 首先确保整个真正的黑客追款方案是最...

猪肉怎么选?颜色有区别吗?今天做饭的时候发现上次买的猪肉颜色跟这

猪肉怎么选?颜色有区别吗?今天做饭的时候发现上次买的猪肉颜色跟这 买猪肉时,根据肉的颜色、外观、气味等可以判断出肉的质量是好还是坏。优质的猪肉,脂肪白而硬,且带有香味。肉的外面往往有一层稍带干燥的膜,肉质紧密,富有弹性,手指压后凹陷处立即复原。 次鲜肉肉色较鲜肉暗,缺乏光泽,脂肪呈灰白色;表面带...

今天发生的重大新闻5条,国内新闻最新消息10条

近期发生的额十件大新闻,伊朗重申继续实施核计划。本·拉登被击毙,近期国内外新闻要近期。 被关闭·国家最高科学技术奖揭晓"青藏铁路工程"等获奖·广西陆川一在建楼面坍塌14名工人坠地受伤,文汇报,执政党民族解放党总统,到了主要内容介绍完。 这是初中作业吧!月1日—德国总理默克尔倡议成立联合国经济理事会。...

中铁快运寄件电话 - 中铁快运官方网站

尽快前去领取吧,查询可以来我们,包裹已经到石家庄了,告诉对方所寄何物。广木头箱子费用在及时上百不等。 .网站“中铁快运单号查询系统”留言查询,开始不知道。 中铁快运的,且电话通知无人接听,但是价格也很贵。在哪里寄,中铁快运,电话多少中铁。 打了个电话,K54,徐州中铁快运,你好,木头箱子中铁能提供。...

蜂胶多少钱一瓶是真的(蜂胶五毒膏多少钱一只)

之前听说这客户有糖尿病,蜂胶就是物稀价贵,变成日常可以食用的营养品。 我经常买的澳佳宝的120左右220粒。如果是纯蜂蜜的话,一般是100-300之间的,59块钱一瓶,在100~300是左右不等,总钱黄酮大于4000mg/100g的含量,一定要注意通过正规的渠道购买,我只知道麦金利的。 蜂胶软胶囊价...

存储过程oracle(oracle财务系统)

推荐教程:甲骨文教程 本文主要介绍甲骨文中的数据转换。 1.日期转换成字符串(以2016年10月20日为例) 选择to_char(sysdate,& # 39;yyyy-mm-DD hh24:mi:ss & # 39;)strDateTime从dual-获取年-月-日:分:秒-...

评论列表

辙弃鹿鸢
2年前 (2022-06-04)

修改Touch事件  控制ViewPager的Touch事件,这个基本是万能的,毕竟是从根源上入手的。你可以在onTouchEvent和onInterceptTouchEvent中做逻辑的判断。但是比较麻烦。  3.4

颜于里赴
2年前 (2022-06-04)

经存在的话,再次设置就直接抛出异常,那么这里可以增强一下逻辑判断,ok,那么问题便解决呢!  try { //attachToRecyclerView源码上的方法可能会抛出IllegalStateException异

颜于邶谌
2年前 (2022-06-04)

tion) { if (isVertical) { if (position < -1) { page.setAlpha(0); } else if (position <= 1) { page.setAlpha(1);

寻妄征棹
2年前 (2022-06-04)

一页的数据。  5.7 上拉很快翻页黑屏  因为设置视频的背景颜色为黑色,我看了好多播放器初始化的时候,都是这样的。因为最简单的解决办法,就是给它加个封面,设置封面的背景即可。

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。