{"id":28581622,"url":"https://github.com/xingstarx/inkeverticalviewpagerlive","last_synced_at":"2025-07-20T01:34:52.036Z","repository":{"id":83124034,"uuid":"75479596","full_name":"xingstarx/InkeVerticalViewPagerLive","owner":"xingstarx","description":"仿映客viewPager上下滑动切换直播","archived":false,"fork":false,"pushed_at":"2021-06-15T09:19:38.000Z","size":61241,"stargazers_count":274,"open_issues_count":9,"forks_count":80,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-06-11T04:17:56.174Z","etag":null,"topics":["android","inke","verticalviewpager","viewpager"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xingstarx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-12-03T14:47:27.000Z","updated_at":"2025-03-07T03:55:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"bbd2bd22-3bd6-4a90-b952-8242413962e7","html_url":"https://github.com/xingstarx/InkeVerticalViewPagerLive","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/xingstarx/InkeVerticalViewPagerLive","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xingstarx%2FInkeVerticalViewPagerLive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xingstarx%2FInkeVerticalViewPagerLive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xingstarx%2FInkeVerticalViewPagerLive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xingstarx%2FInkeVerticalViewPagerLive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xingstarx","download_url":"https://codeload.github.com/xingstarx/InkeVerticalViewPagerLive/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xingstarx%2FInkeVerticalViewPagerLive/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266053867,"owners_count":23869499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","inke","verticalviewpager","viewpager"],"created_at":"2025-06-11T04:17:49.820Z","updated_at":"2025-07-20T01:34:52.006Z","avatar_url":"https://github.com/xingstarx.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InkeVerticalViewPagerLive\n仿映客viewPager上下滑动切换直播demo\n\n##效果预览\n![Screenshot](art/inke.gif)\n\n##APK地址\n[InkeVerticalViewPagerLive-sample.apk](apk/InkeVerticalViewPagerLive-sample.apk)\n\n##简述\n经过几天对映客APP的分析研究，明白了映客上下滑动切换新的直播的实现原理，真心觉得做的挺赞的。。还是很流畅的，性能也很不错。\n\n##思路\n\n首先是一个主Activity，里面只有一个ViewPager，当然了这个viewPager得是VerticalViewPager的。可以参考这两个项目，https://github.com/kaelaela/VerticalViewPager ,\nhttps://github.com/castorflex/VerticalViewPager  ， 请记住ViewPager使用的adapter得是PagerAdapter，而不能是FragmentPagerAdapter\n\n```java\nclass PagerAdapter extends android.support.v4.view.PagerAdapter {\n\n        @Override\n        public int getCount() {\n            return mVideoUrls.size();\n        }\n\n        @Override\n        public boolean isViewFromObject(View view, Object object) {\n            return view == object;\n        }\n\n        @Override\n        public Object instantiateItem(ViewGroup container, int position) {\n            View view = LayoutInflater.from(container.getContext()).inflate(R.layout.view_room_item, null);\n            view.setId(position);\n            container.addView(view);\n            return view;\n        }\n\n        @Override\n        public void destroyItem(ViewGroup container, int position, Object object) {\n            container.removeView(container.findViewById(position));\n        }\n    }\n```\n\n\n大致上就是这样的。 view_room_item.xml的布局，其实很简单，就是一个临时的布局，而不是我们真实的布局，贴一下布局代码吧\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cFrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\u003e\n\n    \u003cImageView\n        android:id=\"@+id/anchor_img\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@drawable/bg_room_change\"\n        android:scaleType=\"fitXY\" /\u003e\n\u003c/FrameLayout\u003e\n```\n\n至于我们的真实业务的布局在哪呢，我们接下来会说道。viewPager上下切换中，创建的都是这个假的临时的布局，而且在整个viewPager起作用的过程中，始终就只有这一个真实业务的布局，viewPager默认会加载三个view，另外两个view都是假的，或者说是临时的view，而在这里，真实业务的布局就是我们的聊天室，以及texttureview\n\nview_room_container.xml\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/room_container\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\u003e\n\n    \u003ccom.pili.pldroid.player.widget.PLVideoTextureView\n        android:id=\"@+id/texture_view\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" /\u003e\n\n    \u003cFrameLayout\n        android:id=\"@+id/fragment_container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" /\u003e\n\u003c/RelativeLayout\u003e\n```\n我们是在什么地方把真实业务布局添加到viewPager中呢，可以看下面的一段代码\n```java\nmViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {\n            @Override\n            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n                Log.e(TAG, \"mCurrentId == \" + position + \", positionOffset == \" + positionOffset +\n                        \", positionOffsetPixels == \" + positionOffsetPixels);\n                mCurrentItem = position;\n            }\n        });\n\nmViewPager.setPageTransformer(false, new ViewPager.PageTransformer() {\n            @Override\n            public void transformPage(View page, float position) {\n                ViewGroup viewGroup = (ViewGroup) page;\n                Log.e(TAG, \"page.id == \" + page.getId() + \", position == \" + position);\n\n                if ((position \u003c 0 \u0026\u0026 viewGroup.getId() != mCurrentItem)) {\n                    View roomContainer = viewGroup.findViewById(R.id.room_container);\n                    if (roomContainer != null \u0026\u0026 roomContainer.getParent() != null \u0026\u0026 roomContainer.getParent() instanceof ViewGroup) {\n                        ((ViewGroup) (roomContainer.getParent())).removeView(roomContainer);\n                    }\n                }\n                // 满足此种条件，表明需要加载直播视频，以及聊天室了\n                if (viewGroup.getId() == mCurrentItem \u0026\u0026 position == 0 \u0026\u0026 mCurrentItem != mRoomId) {\n                    if (mRoomContainer.getParent() != null \u0026\u0026 mRoomContainer.getParent() instanceof ViewGroup) {\n                        ((ViewGroup) (mRoomContainer.getParent())).removeView(mRoomContainer);\n                    }\n                    loadVideoAndChatRoom(viewGroup, mCurrentItem);\n                }\n            }\n         });\n```\n\n在PageTransformer里面，我们需要判断，每时每刻都只有一个真实业务的view，具体的判断条件可以参考这个demo，也可以自己做实验印证，主要的思路还是当滑动停止下来后，transformPage()方法中，当前选中的view的position==0，这个时候我们是需要加载直播视频和聊天室的，\n而view不是我们选中的view的时候，也就是`position \u003c 0 \u0026\u0026 viewGroup.getId() != mCurrentItem` 需要移除之前的真实业务布局。具体可以看上面的代码\n\n\n大致原理就是如此了，请运行demo吧，有疑问，请提issue。\n\n##总结\n整体而言就是ViewPager加载的三个view中，有且只有一个view是拥有视频播放的textureview的，以及聊天室的fragment的，另外两个view都只是显示背景，没有其他的作用，在整个activity的生命过程中，始终只有这一个textutreview以及一个聊天室的fragment的，永远是复用的。这种情况下，就需要自己来控制不出现错位，混乱的问题，对映客的这种方式表示吊吊的 ^_^\n\n##Thanks\n\n视频播放使用的是https://github.com/pili-engineering/PLDroidPlayer ，感觉用起来还是不错的\n\n上下滑动选用的是https://github.com/castorflex/VerticalViewPager ,没有选择另外一个的原因是滑动的产生的波纹效果还是左右方向的，当滑动到顶部或者是底部的时候\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxingstarx%2Finkeverticalviewpagerlive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxingstarx%2Finkeverticalviewpagerlive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxingstarx%2Finkeverticalviewpagerlive/lists"}