Android仿抖音上下滑动切换视频
https://www.jianshu.com/p/af9c0e46725d

 自从各大直播平台可以滑动切换直播间后,公司就出了一大波需求,还要配合各种收费,各种VIP,很是头疼(haha 主要是我这个人很懒,不想加班),后来研究了下 ,也查阅了一些别人写的demo和一些想法,也对此有了一些理解。

  • 1 最开始是打算用RecyclerView来实现的,因为他的复用性很强,用起来也很方便,和SnapHelper相结合便可以实现滑动分页的功能。
    什么是 SnapHelper
    SnapHelper是一个抽象类,官方提供了一个LinearSnapHelper的子类,可以让RecyclerView滚动停止时相应的Item停留中间位置。在25.1.0版本中,官方又提供了一个PagerSnapHelper的子类,可以使RecyclerView像ViewPager一样的效果,一次只能滑一页,而且居中显示。详细源码解读可以看这里让你明明白白的使用RecyclerView——SnapHelper详解,这里我们用到的就是PagerSnapHelper。
    如何使用
    使用非常简单,只需要创建对象之后调用attachToRecyclerView()附着到对应的RecyclerView对象上就可以了。
        snapHelper = new PagerSnapHelper();snapHelper.attachToRecyclerView(rvPage2);

 设置Adapter

        videoAdapter = new ListVideoAdapter(urlList);layoutManager = new LinearLayoutManager(Page2Activity.this, LinearLayoutManager.VERTICAL, false);rvPage2.setLayoutManager(layoutManager);rvPage2.setAdapter(videoAdapter);

 这样我们就只需要监听RecyclerView的滚动,然后就可以实现我们的逻辑了

  rvPage2.addOnScrollListener(new RecyclerView.OnScrollListener() {@Overridepublic void onScrolled(RecyclerView recyclerView, int dx, int dy) {}@Overridepublic void onScrollStateChanged(RecyclerView recyclerView, int newState) {switch (newState) {case RecyclerView.SCROLL_STATE_IDLE://停止滚动View view = snapHelper.findSnapView(layoutManager);//TODO 销毁所有视频RecyclerView.ViewHolder viewHolder = recyclerView.getChildViewHolder(view);if (viewHolder != null && viewHolder instanceof VideoViewHolder) {//TODO  启动想要播放的视频}break;case RecyclerView.SCROLL_STATE_DRAGGING://拖动break;case RecyclerView.SCROLL_STATE_SETTLING://惯性滑动break;}}});
  • 2 不过RecyclerView有个问题,虽然可以达到切换到效果,但是如果我是上下切换,当我左右快速滑动的时候,也会造成上下切换,当然了,这个可以去监听他的触摸事件,只是每一个item里面还有很多事件要处理,冲突性和复杂性会增加很多,就将其设置为备选方案了。所以后来接触到上下切换的VerticalViewPager,就有了其他的方案。

    • A 和V4包的ViewPager使用一样,适配FragmentPagerAdapter,加载多个Fragment,这样的方式其实很简单,很粗暴,不过性能也是很差的,不建议使用
    • B 适配PagerAdapter,监听setPageTransformer,加载新的数据,通过消息传递到Fragment,刷新数据
  class PagerAdapter extends android.support.v4.view.PagerAdapter {private List<HnLiveListModel.LiveListBean> list;public PagerAdapter(List<HnLiveListModel.LiveListBean> list) {this.list = list;}@Overridepublic int getCount() {if (list.size() > 1) {return Integer.MAX_VALUE;} else {return 1;}}@Overridepublic boolean isViewFromObject(View view, Object object) {return view == object;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {View view = LayoutInflater.from(container.getContext()).inflate(R.layout.live_activity_audience_mask_layout, null);int pos = position % list.size();HnLiveListModel.LiveListBean data = list.get(pos);//遮罩层FrescoImageView mFrescoImageView = (FrescoImageView) view.findViewById(R.id.fiv_mask);mFrescoImageView.setVisibility(View.VISIBLE);if (data != null) {String avator = data.getAvator();mFrescoImageView.setController(FrescoConfig.getController(avator));}view.setId(position);container.addView(view);return view;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView(container.findViewById(position));}}
  mVerticalViewPager.setPageTransformer(false, new ViewPager.PageTransformer() {private float yPosition;public float getPosition() {return yPosition;}@Overridepublic void transformPage(View page, float position) {page.setTranslationX(page.getWidth() * -position);yPosition = position * page.getHeight();page.setTranslationY(yPosition);ViewGroup viewGroup = (ViewGroup) page;HnLogUtils.i(TAG, "page.id == " + page.getId() + ", position == " + position);if ((position < 0 && viewGroup.getId() != mCurrentItem)) {View roomContainer = viewGroup.findViewById(R.id.room_container);if (roomContainer != null && roomContainer.getParent() != null && roomContainer.getParent() instanceof ViewGroup) {((ViewGroup) (roomContainer.getParent())).removeView(roomContainer);}}// 满足此种条件,表明需要加载直播视频,以及聊天室了if (viewGroup.getId() == mCurrentItem && position == 0 && mCurrentItem != mRoomUid) {if (mRoomContainer.getParent() != null && mRoomContainer.getParent() instanceof ViewGroup) {((ViewGroup) (mRoomContainer.getParent())).removeView(mRoomContainer);}EventBus.getDefault().post(new HnLiveEvent(0, HnLiveConstants.EventBus.Close_Dialog, 0));EventBus.getDefault().post(new HnLiveEvent(0, HnLiveConstants.EventBus.Hide_Mask, 0));loadVideoAndChatRoom(viewGroup, mCurrentItem);}}});/*** 加载房间信息** @param viewGroup* @param mCurrentItem*/private void loadVideoAndChatRoom(ViewGroup viewGroup, int mCurrentItem) {pos = mCurrentItem % list.size();HnLogUtils.i(TAG, "当前加载的位置:" + pos + "--->" + mCurrentItem);HnLiveListModel.LiveListBean bean = list.get(pos);//聊天室的fragment只加载一次,以后复用if (!mInit) {mRoomFragment = HnAudienceRoomFragment.newInstance(bean);mFragmentManager.beginTransaction().replace(R.id.fragment_container, mRoomFragment).commitAllowingStateLoss();mInit = true;} else {if (mRoomFragment == null) {mRoomFragment = HnAudienceRoomFragment.newInstance(bean);mFragmentManager.beginTransaction().replace(R.id.fragment_container, mRoomFragment).commitAllowingStateLoss();mInit = true;}EventBus.getDefault().post(new HnLiveEvent(0, HnLiveConstants.EventBus.Update_Room_Info, bean));}viewGroup.addView(mRoomContainer);this.mRoomUid = mCurrentItem;}
  • C 适配PagerAdapter,初始化每个Item的View ,以View为数据源,适配到adapter中(不过直播中业务复杂,不推荐在直播中使用,小视频可以使用(直接一次性将数据传递过来)),这个方式主要是为了复用播放器,这样就不要添加多个播放器了
   for (HnChatVideoSwitchEntity item : mList) {if (mActivity == null) return;View view = LayoutInflater.from(mActivity).inflate(R.layout.adapter_invite_chat, null);//TODO  初始化控件//TODO  设置点击事件//TODO  设置数据mViews.add(view);}

adapter里面很简单

public class HnInviteChatAdapter extends PagerAdapter {private static final String TAG = "DouYinAdapter";private List<View> mViews;public HnInviteChatAdapter(List<View> views) {this.mViews = views;}public void setmViews(List<View> mViews) {this.mViews = mViews;}@Overridepublic int getCount() {return mViews.size();}@Overridepublic boolean isViewFromObject(@NonNull View view, @NonNull Object object) {return view == object;}@NonNull@Overridepublic Object instantiateItem(@NonNull ViewGroup container, int position) {Log.d(TAG, "instantiateItem: called");container.addView(mViews.get(position));return mViews.get(position);}@Overridepublic void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {Log.d(TAG, "destroyItem: ");container.removeView(mViews.get(position));}}

然后当滑动ViewPager时,重置数据就可以了

  mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {@Overridepublic void onPageSelected(int position) {mCurrentItem = position;//TODO视频暂停播放if (mIjkVideoView != null) {mIjkVideoView.pause();}}@Overridepublic void onPageScrollStateChanged(int state) {if (mPlayingPosition == mCurrentItem) return;if (state == VerticalViewPager.SCROLL_STATE_IDLE) {//TODO视频暂停播放stopPlay();//TODO 重置一些控件显示与否releaseView();ViewParent parent = mIjkVideoView.getParent();//TODO移除上个页面的视频控件if (parent != null && parent instanceof FrameLayout) {((FrameLayout) parent).removeView(mIjkVideoView);}getAnchorData(mCurrentItem);}}});

然后就是更新数据了

 private void getAnchorData(int position) {mUid = mList.get(position).getUser_id();mDbean = mList.get(position);mPlayUrl = mDbean.getUser_video();mCurrentItem = position;View view = mViews.get(mCurrentItem);RelativeLayout mContainer = view.findViewById(R.id.mContainer);initItemView(view);//TODO 设置控件数据和状态//添加播放器ViewGroup parent = (ViewGroup) mIjkVideoView.getParent();if (parent != null) {parent.removeAllViews();}RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);params.addRule(RelativeLayout.CENTER_IN_PARENT);mIjkVideoView.setLayoutParams(params);mContainer.addView(mIjkVideoView, 0, params);startPlay();mPlayingPosition = mCurrentItem;}

作者:TXswim
链接:https://www.jianshu.com/p/af9c0e46725d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Android仿抖音上下滑动切换视频相关推荐

  1. iOS仿抖音上下滑动播放视频

    首先看下效果图 前言 上一篇文章仿写了抖音的左右滑动效果-iOS之仿抖音左右滑动效果,有兴趣的可以去GKNavigationBarViewController的demo中查看. 这篇文章主要是对抖音的 ...

  2. 仿抖音上下滑动播放视频 demo+爱心点赞特效

    DouyinDemo 项目地址:PangHaHa12138/DouyinDemo  简介:仿抖音上下滑动播放视频 demo+爱心点赞特效 更多:作者   提 Bug 标签: 仿抖音上下滑动播放视频 d ...

  3. 抖音只能上下滑动吗_iOS仿抖音—上下滑动播放视频

    iOS仿抖音短视频 图做的不太好,将就看吧 2018.12.12 添加了tabbar,数据写死到了本地(接口过一段时间就会访问没数据) dy_tabbar.gif 前言 上一篇文章仿写了抖音的左右滑动 ...

  4. 仿抖音上下滑动分页视频

    目录介绍 01.先来看一下需求 02.有几种实现方式 2.1 使用ViewPager 2.2 使用RecyclerView 03.用ViewPager实现 3.1 自定义ViewPager 3.2 V ...

  5. 抖音只能上下滑动吗_仿抖音上下滑动播放视频

    太多朋友对短视频,上下滚动播放视频效果比较比较研究,今天看看这个案例. 讲下大概思路,使用Recycleview配合自定义LinearLayoutManager来实现这个功能,这里着重说下自定义Lin ...

  6. 微信小程序仿抖音上下滑动整屏切换视频

    微信小程序仿抖音上下滑动整屏切换视频 使用官网上面的扩展组件 官方使用的方式: 可结合自己业务修改: 使用官网上面的扩展组件 https://developers.weixin.qq.com/mini ...

  7. android仿抖音直播间聊天,Uni-App直播小视频|仿微信聊天界面|uniapp仿抖音

    U直播是一个基于Nvue+vue+uniapp技术开发的仿抖音小视频.陌陌直播的项目.小视频及直播页面均实现了类似抖音上下滑动切换效果,还有点赞.评论.商品等功能展示. 运行效果: 技术实现:编辑器+ ...

  8. Android 仿抖音视频播放列表和评论列表

    Android 汇集CSDN.GitHub等最实用的良心之作-KING Android最实用的各种技能点的网址链接(每天都会更新,希望大家用的上) Android 仿抖音系列之视频播放列表和评论列表 ...

  9. 基于android的高仿抖音,Android仿抖音列表效果

    本文实例为大家分享了Android仿抖音列表效果的具体代码,供大家参考,具体内容如下 当下抖音非常火热,是不是也很心动做一个类似的app吗? 那我们就用RecyclerView实现这个功能吧,关于内存 ...

最新文章

  1. LTE-连接态下的DRX
  2. 使用drbd进行磁盘扩容,小磁盘扩容大磁盘后大小未变的问题解决方法
  3. export_symbol的使用
  4. apiCloud中图片裁剪模块FNImageClip的使用
  5. 在Linux下安装配置Oracle11g R2
  6. sprintf函数实现_从Go结构成员的升格到面向对象类的实现
  7. zabbix items复制
  8. Code First Migrations更新数据库结构的具体步骤
  9. 写给大忙人的ELK最新版6.2.4学习笔记-Logstash和Filebeat解析(java异常堆栈下多行日志配置支持)
  10. [转载] python 运算符重载有什么用_Python运算符重载用法实例分析
  11. 【detectron】FPN网络输入
  12. js自动触发按键操作
  13. Facebook 应用开发认证和授权登录流程
  14. MPQ文件系统优化(续)
  15. html站点根目在哪,10分钟了解Dreamweaver中站点根目录相对路径
  16. 网站域名要加www吗?没有www会影响网站SEO吗?
  17. Hive中的map join、left semi join和sort merge bucket join
  18. Excel从身份证号提取生日
  19. python编程输入名字配对情侣网名_输入名字制作情侣网名,如何制作甜蜜的情侣网名?...
  20. 所有网站都通用的自定义弹出框alert

热门文章

  1. 实例讲解SQL注入攻击
  2. iOS小技能:对symbol的理解
  3. book mac pro怎么重装系统_Macbook Pro怎么重装系统?
  4. 一个让全球人沉迷的游戏背后需要怎样的团队?
  5. mysql中nvl_oracle中nvl函数在mysql里面怎么使用
  6. Windows如何在命令行(cmd/dos)模式下使用指定应用打开某个文件
  7. zeppelin集成presto
  8. 中国移动点击咪视通,首先请求的CDN的IP地址
  9. vue 验证公民身份证号 并 自动 获取 性别、年龄、生日
  10. vba的if条件函数和range用法超详细介绍