仿抖音上下滑動播放視頻

不少朋友對短視頻,上下滑動播放視頻效果比較比較感興趣,今天看看這個案例。

1、效果圖:

仿抖音上下滑動播放視頻

仿抖音上下滑動播放視頻

仿抖音上下滑動播放視頻

講下大概思路,使用Recycleview配合自定義LinearLayoutManager來實現這個功能,這裡著重說下自定義LinearLayoutManager的實現可以看到每當下一個item滑入屏幕時,上面的item會繼續播放視頻,而滑入的item只有當全部進入屏幕才會播放,而且當手指抬起時,當前item會根據滑動的距離相應的自動滑入滑出,針對這種情形,就會想到使用SnapHelper

RecyclerView在24.2.0版本中新增了SnapHelper這個輔助類,用於輔助RecyclerView在滾動結束時將Item對齊到某個位置。特別是列表橫向滑動時,很多時候不會讓列表滑到任意位置,而是會有一定的規則限制,這時候就可以通過SnapHelper來定義對齊規則了。

SnapHelper是一個抽象類,官方提供了一個LinearSnapHelper的子類,可以讓RecyclerView滾動停止時相應的Item停留中間位置。25.1.0版本中官方又提供了一個PagerSnapHelper的子類,可以使RecyclerView像ViewPager一樣的效果,一次只能滑一頁,而且居中顯示,也就是說使用SnapHelper可以幫助RecyclerView滑動完成後進行對齊操作,讓item的側邊對齊或者居中對齊,這樣實現上下滑動進行視頻切換。這裡有SnapHelper的詳解

2、正式擼代碼:

1.首先定義一個接口,用來執行item的相關操作

```

public interface OnViewPagerListener {

/*初始化完成*/

void onInitComplete();

/*釋放的監聽*/

void onPageRelease(boolean isNext, int position);

/*選中的監聽以及判斷是否滑動到底部*/

void onPageSelected(int position, boolean isBottom);

}

```

2.繼承LinearLayoutManager ,對滑入滑出的item回調1中接口裡面的方法

```

public interface OnViewPagerListener {

/*初始化完成*/

void onInitComplete();

/*釋放的監聽*/

void onPageRelease(boolean isNext, int position);

/*選中的監聽以及判斷是否滑動到底部*/

void onPageSelected(int position, boolean isBottom);

}

```

2.繼承LinearLayoutManager ,對滑入滑出的item回調1中接口裡面的方法

```

import android.content.Context;

import android.support.annotation.NonNull;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.PagerSnapHelper;

import android.support.v7.widget.RecyclerView;

import android.view.View;

public class MyLayoutManager extends LinearLayoutManager implements RecyclerView.OnChildAttachStateChangeListener {

private int mDrift;//位移,用來判斷移動方向

private PagerSnapHelper mPagerSnapHelper;

private OnViewPagerListener mOnViewPagerListener;

public MyLayoutManager(Context context) {

super(context);

}

public MyLayoutManager(Context context, int orientation, boolean reverseLayout) {

super(context, orientation, reverseLayout);

mPagerSnapHelper = new PagerSnapHelper();

}

@Override

public void onAttachedToWindow(RecyclerView view) {

view.addOnChildAttachStateChangeListener(this);

mPagerSnapHelper.attachToRecyclerView(view);

super.onAttachedToWindow(view);

}

//當Item添加進來了 調用這個方法

//

@Override

public void onChildViewAttachedToWindow(@NonNull View view) {

// 播放視頻操作 即將要播放的是上一個視頻 還是下一個視頻

int position = getPosition(view);

if (0 == position) {

if (mOnViewPagerListener != null) {

mOnViewPagerListener.onPageSelected(getPosition(view), false);

}

}

}

public void setOnViewPagerListener(OnViewPagerListener mOnViewPagerListener) {

this.mOnViewPagerListener = mOnViewPagerListener;

}

@Override

public void onScrollStateChanged(int state) {

switch (state) {

case RecyclerView.SCROLL_STATE_IDLE:

View view = mPagerSnapHelper.findSnapView(this);

int position = getPosition(view);

if (mOnViewPagerListener != null) {

mOnViewPagerListener.onPageSelected(position, position == getItemCount() - 1);

}

// postion ---回調 ----》播放

break;

}

super.onScrollStateChanged(state);

}

@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));

}

}

@Override

public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

this.mDrift = dy;

return super.scrollVerticallyBy(dy, recycler, state);

}

@Override

public boolean canScrollVertically() {

return true;

}

}

```

3.接下來就是正常使用recycleview了 配合原生VideoView 播放視頻,切換時先用一張截圖蓋住視頻,視頻渲染成功再隱藏截圖,感覺上是無縫切換(這裡是原生播放器初始加載視頻會黑屏,如果用更高級的播放器可能不會有這個問題)

```

import android.annotation.TargetApi;

import android.content.Context;

import android.media.MediaPlayer;

import android.net.Uri;

import android.os.Build;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.support.v7.widget.OrientationHelper;

import android.support.v7.widget.RecyclerView;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.ImageView;

import android.widget.RelativeLayout;

import android.widget.VideoView;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "douyin";

private RecyclerView mRecyclerView;

private MyAdapter mAdapter;

MyLayoutManager2 myLayoutManager;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initView();

initListener();

}

private void initView() {

mRecyclerView = findViewById(R.id.recycler);

myLayoutManager = new MyLayoutManager2(this, OrientationHelper.VERTICAL, false);

mAdapter = new MyAdapter(this);

mRecyclerView.setLayoutManager(myLayoutManager);

mRecyclerView.setAdapter(mAdapter);

}

private void initListener() {

myLayoutManager.setOnViewPagerListener(new OnViewPagerListener() {

@Override

public void onInitComplete() {

}

@Override

public void onPageRelease(boolean isNext, int position) {

Log.e(TAG, "釋放位置:" + position + " 下一頁:" + isNext);

int index = 0;

if (isNext) {

index = 0;

} else {

index = 1;

}

releaseVideo(index);

}

@Override

public void onPageSelected(int position, boolean bottom) {

Log.e(TAG, "選擇位置:" + position + " 下一頁:" + bottom);

playVideo(0);

}

});

}

class MyAdapter extends RecyclerView.Adapter<myadapter.viewholder> {/<myadapter.viewholder>

private int[] imgs = {R.mipmap.img_video_1, R.mipmap.img_video_2, R.mipmap.img_video_3, R.mipmap.img_video_4, R.mipmap.img_video_5, R.mipmap.img_video_6, R.mipmap.img_video_7, R.mipmap.img_video_8};

private int[] videos = {R.raw.video_1, R.raw.video_2, R.raw.video_3, R.raw.video_4, R.raw.video_5, R.raw.video_6, R.raw.video_7, R.raw.video_8};

private int index = 0;

private Context mContext;

public MyAdapter(Context context) {

this.mContext = context;

}

@Override

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view_pager, parent, false);

return new ViewHolder(view);

}

@Override

public void onBindViewHolder(ViewHolder holder, int position) {

holder.img_thumb.setImageResource(imgs[index]);

holder.videoView.setVideoURI(Uri.parse("android.resource://" + getPackageName() + "/" + videos[index]));

index++;

if (index >= 7) {

index = 0;

}

}

@Override

public int getItemCount() {

return 88;

}

public class ViewHolder extends RecyclerView.ViewHolder {

ImageView img_thumb;

VideoView videoView;

ImageView img_play;

RelativeLayout rootView;

public ViewHolder(View itemView) {

super(itemView);

img_thumb = itemView.findViewById(R.id.img_thumb);

videoView = itemView.findViewById(R.id.video_view);

img_play = itemView.findViewById(R.id.img_play);

rootView = itemView.findViewById(R.id.root_view);

}

}

}

private void releaseVideo(int index) {

View itemView = mRecyclerView.getChildAt(index);

final VideoView videoView = itemView.findViewById(R.id.video_view);

final ImageView imgThumb = itemView.findViewById(R.id.img_thumb);

final ImageView imgPlay = itemView.findViewById(R.id.img_play);

videoView.stopPlayback();

imgThumb.animate().alpha(1).start();

imgPlay.animate().alpha(0f).start();

}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)

private void playVideo(int position) {

View itemView = mRecyclerView.getChildAt(position);

final FullWindowVideoView videoView = itemView.findViewById(R.id.video_view);

final ImageView imgPlay = itemView.findViewById(R.id.img_play);

final ImageView imgThumb = itemView.findViewById(R.id.img_thumb);

final RelativeLayout rootView = itemView.findViewById(R.id.root_view);

final MediaPlayer[] mediaPlayer = new MediaPlayer[1];

videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

@Override

public void onPrepared(MediaPlayer mp) {

}

});

videoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {

@Override

public boolean onInfo(MediaPlayer mp, int what, int extra) {

mediaPlayer[0] = mp;

mp.setLooping(true);

imgThumb.animate().alpha(0).setDuration(200).start();

return false;

}

});

videoView.start();

imgPlay.setOnClickListener(new View.OnClickListener() {

boolean isPlaying = true;

@Override

public void onClick(View v) {

if (videoView.isPlaying()) {

imgPlay.animate().alpha(0.7f).start();

videoView.pause();

isPlaying = false;

} else {

imgPlay.animate().alpha(0f).start();

videoView.start();

isPlaying = true;

}

}

});

}

}

```

原創作者:龐哈哈哈12138,原文:https://www.jianshu.com/p/3a043cd4eb1f

仿抖音上下滑動播放視頻


歡迎關注我的微信公眾號「碼農突圍」,分享Python、Java、大數據、機器學習、人工智能等技術,關注碼農技術提升•職場突圍•思維躍遷,20萬+碼農成長充電第一站,陪有夢想的你一起成長。


分享到:


相關文章: