在 recyclerview 中流畅地播放来自 URL 的视频

Posted

技术标签:

【中文标题】在 recyclerview 中流畅地播放来自 URL 的视频【英文标题】:Smoothly Play video from URL in recyclerview 【发布时间】:2019-10-26 05:17:40 【问题描述】:

我尝试在 Recyclerview 中播放视频,但无法正常工作。为此,我使用了:https://github.com/danylovolokh/VideoPlayerManager。

谁能告诉我相同的替代解决方案。

【问题讨论】:

【参考方案1】:

根据需要修改


    @BindView(R.id.rv_home) RecyclerView recyclerView;

    private static final String TAG = "HomeFragment";

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        requestForRead();
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        View view =  inflater.inflate(R.layout.fragment_home, container, false);
        ButterKnife.bind(this, view);

        setRecyclerView();

        if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
            new VideosAsync(getContext()).execute();
        else
            requestForRead();

        return view;
    

    private void setRecyclerView()
        LinearSnapHelper linearSnapHelper = new SnapHelperOneByOne();
        linearSnapHelper.attachToRecyclerView(recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    


    //get list of videos
    private List<String> getAllMedia() 
        HashSet<String> videoItemHashSet = new HashSet<>();
        String[] projection =  MediaStore.Video.VideoColumns.DATA;
        Cursor cursor = getContext().getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection
                , null, null, null);
        try 
            cursor.moveToFirst();
            do
                String path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
                videoItemHashSet.add(path);
            
            while(cursor.moveToNext());

            cursor.close();
         catch (Exception e) 
            e.printStackTrace();
        
        return new ArrayList<>(videoItemHashSet);
    


    private void requestForRead()
        ActivityCompat.requestPermissions( getActivity(), new String[]Manifest.permission.READ_EXTERNAL_STORAGE, 100);
    

    public class VideosAsync extends AsyncTask<Void, Void, List<String>> 
        private Context context;
        private List<String> videoList;

        public VideosAsync(Context context) 
            this.context = context;
            this.videoList = new ArrayList<>();
        

        @Override
        protected List<String> doInBackground(Void... params) 
            videoList.addAll(getAllMedia());
            return videoList;
        

        @Override
        protected void onPostExecute(List<String> videos) 
            HomeAdapter adapter = new HomeAdapter(videos, context);
            recyclerView.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        

        @Override
        protected void onPreExecute() 
        
    

SnapHelperOneByOne

public class SnapHelperOneByOne extends LinearSnapHelper

    @Override
    public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY)

        if (!(layoutManager instanceof RecyclerView.SmoothScroller.ScrollVectorProvider)) 
            return RecyclerView.NO_POSITION;
        

        final View currentView = findSnapView(layoutManager);

        if( currentView == null )
            return RecyclerView.NO_POSITION;
        

        final int currentPosition = layoutManager.getPosition(currentView);

        if (currentPosition == RecyclerView.NO_POSITION) 
            return RecyclerView.NO_POSITION;
        

        return currentPosition;
    

适配器

public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.ViewHolder> 

    private List<String> videoList;
    private Context context;

    public HomeAdapter(List<String> videoList, Context context) 
        this.videoList = videoList;
        this.context = context;
    

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) 
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_video_home, parent, false));
    

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) 
        Uri path = Uri.parse(videoList.get(position));
        setVideoView(holder, path);
    

    @Override
    public int getItemCount() 
        return videoList.size();
    

    public class ViewHolder extends RecyclerView.ViewHolder 
        @BindView(R.id.video_view_home) FullScreenVideoView fullScreenVideoView;

        public ViewHolder(@NonNull View itemView) 
            super(itemView);
            ButterKnife.bind(this, itemView);
        
    

    private void setVideoView(ViewHolder holder, Uri videoPath)
        holder.fullScreenVideoView.seekTo(100);
        holder.fullScreenVideoView.setVideoURI(videoPath);
        holder.fullScreenVideoView.requestFocus();
        holder.fullScreenVideoView.setOnPreparedListener(mp -> 
            mp.setLooping(true);

            //Set the surface holder height to the screen dimensions
            holder.fullScreenVideoView.start();
        );
    

适配器的行布局

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_
    android:layout_>

    <RelativeLayout
        android:layout_
        android:layout_>

        <com.codencolors.myapplication.helper.FullScreenVideoView
            android:id="@+id/video_view_home"
            android:layout_alignParentTop="true"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_
            android:layout_ />

        <LinearLayout
            android:layout_alignParentEnd="true"
            android:layout_marginEnd="20dp"
            android:layout_centerVertical="true"
            android:layout_
            android:layout_
            android:orientation="vertical">

            <ImageView
                android:layout_
                android:layout_
                android:src="@drawable/ic_heart"/>

            <ImageView
                android:layout_marginTop="20dp"
                android:layout_
                android:layout_
                android:src="@drawable/ic_message"/>

            <ImageView
                android:layout_marginTop="20dp"
                android:layout_
                android:layout_
                android:src="@drawable/ic_forward"/>

        </LinearLayout>



    </RelativeLayout>

</LinearLayout>

片段布局

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".fragments.HomeFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv_home"
        android:layout_
        android:layout_/>

</FrameLayout>

清单权限


    <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

【讨论】:

以上是关于在 recyclerview 中流畅地播放来自 URL 的视频的主要内容,如果未能解决你的问题,请参考以下文章

如何优化 mp4 视频以在浏览器中尽可能流畅地播放 (HTML5)

在recyclerview中使用textureview播放视频

Android:如何流畅地按顺序播放视频而不会出现故障和延迟?

我如何使用来自firebase的数据制作recyclerview,并有意图地点击

一个接一个地同时流畅地播放视频[没有可见的从一个切换到另一个]

GapWorker导致RecyclerView视频播放声音残留问题