动手写一个抖音首页的效果

Posted 有心好书

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动手写一个抖音首页的效果相关的知识,希望对你有一定的参考价值。

如何实现一个抖音首页的沉浸式视频播放效果

01.疑问

怎么实现一个顺畅的类似抖音的沉浸式播放效果

02.方案

方案1:viewpager+复用,低端机教卡
方案2:recycleview,比较顺畅
方案3:viewpager2

03.实现

public class TestActivity extends BaseActivity 
    LinearLayoutManager mLinearLayoutManager;
    int preShowPosition;
    TestListAdapter madapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_test_test);

        RecyclerView recyclerView = findViewById(R.id.rv);

        madapter = new TestListAdapter(this);
        ArrayList<Object> objects = new ArrayList<>();
        objects.add("http://vjs.zencdn.net/v/oceans.mp4");
        objects.add("http://vjs.zencdn.net/v/oceans.mp4");
        objects.add("http://vjs.zencdn.net/v/oceans.mp4");
        objects.add("http://vjs.zencdn.net/v/oceans.mp4");
        objects.add("http://vjs.zencdn.net/v/oceans.mp4");
        new PagerSnapHelper().attachToRecyclerView(recyclerView);
        mLinearLayoutManager = new LinearLayoutManager(mContext) 
            public boolean canScrollVertically() 
                return super.canScrollVertically();
            
        ;
        recyclerView.setLayoutManager(mLinearLayoutManager);
        recyclerView.setAdapter(madapter);
        madapter.setNewData(objects);
        recyclerView.addOnScrollListener(new MyScrollListener());
    

    class MyScrollListener extends RecyclerView.OnScrollListener 
        public MyScrollListener() 
        

        public void onScrollStateChanged(RecyclerView recyclerView, int newState) 
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == 0
                    && mLinearLayoutManager.findFirstVisibleItemPosition() != -1) 
                int position = mLinearLayoutManager.findFirstVisibleItemPosition();
                if (preShowPosition < position) 
                    preShowPosition = position;
                    if (madapter.getData().size() > position + 1) 
                        // 对上一个下一个做预处理
                    
                 else if (preShowPosition > position) 
                    preShowPosition = position;
                    if (position != 0) 

                    
                
                TestBlock block =
                        (TestBlock) mLinearLayoutManager.findViewByPosition(position);
                block.startVideo();
            
        

        public void onScrolled(RecyclerView recyclerView, int dx, int dy) 
            super.onScrolled(recyclerView, dx, dy);
        
    

public class TestBlock extends FrameLayout 

    private Context mContext;
    private XXVideoView XXVideoView;

    public TestBlock(@NonNull Context context) 
        this(context, null);
    

    public TestBlock(@NonNull Context context,
                     @Nullable AttributeSet attrs) 
        super(context, attrs);
        init(context);
    

    private void init(Context context) 
        mContext = context;
        inflate(mContext, R.layout.layout_sticky_header_view, this);
        setLayoutParams(
                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        XXVideoView = findViewById(R.id.tv_sticky_header_view);
        XXVideoView.setLoop(true);
        XXVideoView.setAlpha(1f);
    

    public void setData(String url) 
        XXVideoView.setVideoPath(url);
    

    public void startVideo() 
        XXVideoView.start();
    



public class TestListAdapter extends BaseTypeAdapter<Object> 
    private final int TYPE_SECTION_DATE = -1;
    private Activity mActivity;

    public TestListAdapter(Activity activity) 
        this.mActivity = activity;
    

    @Override
    protected View createView(int type, ViewGroup parent) 
        View ret = null;
        switch (type) 
            case TYPE_SECTION_DATE:
                ret = new TestBlock(mActivity);
                break;
        
        return ret;
    

    @Override
    protected int getType(int position, Object data) 
        if (data instanceof String) 
            return TYPE_SECTION_DATE;
         else 
            return TYPE_COMMOM;
        
    

    @Override
    protected void bindData(BaseViewHolder holder, Object data, int position, int type) 
        switch (type) 
            case TYPE_SECTION_DATE:
                TestBlock block = (TestBlock) holder.getConvertView();
                block.setData("http://vjs.zencdn.net/v/oceans.mp4");
                break;
        
    

当然只是实现了,简单的效果,各种预加载等等并未处理

04.参考资料

让你明明白白的使用RecyclerView——SnapHelper详解
https://www.jianshu.com/p/e54db232df62

你们要的抖音效果来了
http://www.10tiao.com/html/169/201806/2650825600/1.html

viewpager2原理和使用
https://www.jianshu.com/p/6d46c89069f8
这个目前还不稳定

以上是关于动手写一个抖音首页的效果的主要内容,如果未能解决你的问题,请参考以下文章

动手来写一个EventBus吧~~~~

仿支付宝首页头部伸缩效果

揭秘抖音春节爆款 AR 道具背后的“秘密”

字节面试记录

抖音同款课堂点名系统PyQt5写起来很简单

为什么博客园-设置-自己写的页首页脚代码只有自己登录的页面有效果