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

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

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
这个目前还不稳定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值