java VideoView onTouch 事件:暂停/恢复视频,以及显示/隐藏 MediaController 和 ActionBar

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26700315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:25:47  来源:igfitidea点击:

VideoView onTouch events: pause/resume video, and show/hide MediaController and ActionBar

javaandroidvideoandroid-videoview

提问by pez

Question summary:

问题总结:

1) How to first display the video as paused, and not play it immediately?

1) 如何先将视频显示为暂停状态,而不是立即播放?

2) How to pause/un-pause the video on touch, and also hide/show the ActionBar and MediaController.

2) 如何在触摸时暂停/取消暂停视频,以及隐藏/显示 ActionBar 和 MediaController。

I'd appreciate any advice. Thanks! (Relevant Code is attached)

我很感激任何建议。谢谢!(附上相关代码)

Update 1

更新 1

Found somewhat of a solution to question 2 (needed to return false), but I still don't know how to answer question 1.

找到了问题 2 的一些解决方案(需要返回 false),但我仍然不知道如何回答问题 1。

When the user presses a button in my app, it takes them to watch their video. When they first open that screen, I'd like the video to be paused and not play immediately. I'd also like to be able to pause playback of the video by tapping the screen. When the video is paused, I'd like to show the ActionBarand the MediaController. When the video is resumed, I'd like to hide the ActionBarand MediaController(possibly after a slight delay?)

当用户按下我的应用程序中的按钮时,他们会观看他们的视频。当他们第一次打开那个屏幕时,我希望视频暂停而不是立即播放。我还希望能够通过点击屏幕来暂停视频的播放。当视频暂停时,我想显示ActionBarMediaController。当视频恢复时,我想隐藏ActionBarMediaController(可能稍有延迟?)

I've tried a few things, but I end up with problems, like the video will pause but not resume, or the ActionBarand MediaControllerwill not show or hide properly.

我已经尝试了一些方法,但最终还是遇到了问题,例如视频会暂停但无法恢复,或者ActionBarMediaController无法正确显示或隐藏。

Update 2

更新 2

I have found a partial solution to question 1 and have updated the code to display the video as paused the first time it is opened. However, when it is opened for the first time, it only shows a black screen until I touch the videoview to play it. After watching the video once, it will reset to the beginning and pause, waiting to be played again, and will show the correct image from the beginning of the video. But I don't know how to get around the black screen at the beginning.

我找到了问题 1 的部分解决方案,并更新了代码以将视频显示为第一次打开时暂停。但是,当它第一次打开时,它只显示黑屏,直到我触摸视频视图播放它。观看一次视频后,将重置到开头并暂停,等待再次播放,并从视频开头显示正确的图像。但我不知道如何绕过一开始的黑屏。

Relevant code:

相关代码:

public class ViewImageVideoFragment extends Fragment
{

    private int position = 0;
    private MediaController mMediaController;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        mMediaController = new MediaController(getActivity());
        ...
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
    {

        if (savedInstanceState != null)
        {
            position = savedInstanceState.getInt("position");
        }

        View v = inflater.inflate(R.layout.fragment_video_view, parent, false);

        mVideoView = (VideoView) v.findViewById(R.id.fragmentVideoView);
        mVideoView.setVideoPath(videoPath);
        mVideoView.setMediaController(mMediaController);

        mVideoView.setOnTouchListener(new View.OnTouchListener()
        {
            @Override
            public boolean onTouch(View v, MotionEvent motionEvent)
            {
                if (mVideoView.isPlaying())
                {
                    mVideoView.pause();
                    if (!getActivity().getActionBar().isShowing())
                    {
                        getActivity().getActionBar().show();
                        mMediaController.show(0);
                    }
                    position = mVideoView.getCurrentPosition();
                    return false;
                }
                else
                {
                    if (getActivity().getActionBar().isShowing())
                    {
                        getActivity().getActionBar().hide();
                        mMediaController.hide();
                    }
                    mVideoView.seekTo(position);
                    mVideoView.start();
                    return false;
                }
            }
        });

        mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
        {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer)
            {
                mVideoView.seekTo(0);
            }
        });

        if (position != 0)
        {
            mVideoView.seekTo(position);
            mVideoView.start();
        }
        else
        {
             mVideoView.seekTo(0);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState)
    {
        super.onSaveInstanceState(savedInstanceState);

        if (mVideoView != null)
        {
            savedInstanceState.putInt("position", mVideoView.getCurrentPosition());
        }

        mVideoView.pause();
    }
}

回答by

To first show the video as paused, simply change seekTo(0)to seekTo(1)in your code. This will move the video to the time at 1 millisecond and you can take it from there.

要首先将视频显示为暂停,只需在您的代码中更改seekTo(0)seekTo(1)。这会将视频移动到 1 毫秒的时间,您可以从那里获取它。

//edited here
private int position = 1;
private MediaController mMediaController;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    mMediaController = new MediaController(getActivity());
    ...
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{

    if (savedInstanceState != null)
    {
        position = savedInstanceState.getInt("position");
    }

    View v = inflater.inflate(R.layout.fragment_video_view, parent, false);

    mVideoView = (VideoView) v.findViewById(R.id.fragmentVideoView);
    mVideoView.setVideoPath(videoPath);
    mVideoView.setMediaController(mMediaController);

    mVideoView.setOnTouchListener(new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent motionEvent)
        {
            if (mVideoView.isPlaying())
            {
                mVideoView.pause();
                if (!getActivity().getActionBar().isShowing())
                {
                    getActivity().getActionBar().show();
                    mMediaController.show(0);
                }
                position = mVideoView.getCurrentPosition();
                return false;
            }
            else
            {
                if (getActivity().getActionBar().isShowing())
                {
                    getActivity().getActionBar().hide();
                    mMediaController.hide();
                }
                mVideoView.seekTo(position);
                mVideoView.start();
                return false;
            }
        }
    });

    mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
    {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer)
        {
            //here
            mVideoView.seekTo(1);
        }
    });
    //here
    if (position != 1)
    {
        mVideoView.seekTo(position);
        mVideoView.start();
    }
    else
    {
         //here
         mVideoView.seekTo(1);
    }
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
    super.onSaveInstanceState(savedInstanceState);

    if (mVideoView != null)
    {
        savedInstanceState.putInt("position", mVideoView.getCurrentPosition());
    }

    mVideoView.pause();
}

}

}

回答by Jeff Mixon

If I understand correctly, you want to display a frame from the video as a placeholder until you are ready to start the video. There's two ways I know to accomplish this:

如果我理解正确,您希望将视频中的一帧显示为占位符,直到您准备好开始播放视频。我知道有两种方法可以做到这一点:

seekTo

寻求

You can use MediaPlayer.seekToto move the video some frames ahead, for example using the value 150to display the frame at the 150th millisecond in the video file. The video does not need to be started in order to seek.

您可以使用MediaPlayer.seekTo将视频向前移动一些帧,例如使用该值150在视频文件中的第 150 毫秒处显示帧。视频无需启动即可搜索。

MediaMetadataRetriever

媒体元数据检索器

MediaMetadataRetriever met = new MediaMetadataRetriever();

try { 
    met.setDataSource(data[0], new HashMap<String, String>()); //use this constructor, other one has a bug...
    Bitmap b = met.getFrameAtTime();

    if (b == null)
        b = met.getFrameAtTime(150, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);

    met.release();
    return b;

} catch (Exception e) {
    Log.d(TAG, "MediaMetadata failed", e);
}

This will give you a Bitmapwhich you can then throw in an ImageViewand set in place of the video. However, this API has always been buggy for me depending on the types of video codecs you are dealing with.

这将为您提供一个Bitmap,然后您可以将其放入ImageView并设置在视频的位置。但是,根据您正在处理的视频编解码器的类型,这个 API 对我来说总是有问题。

回答by DreadHeadedDeveloper

My sources --

我的消息来源——

show()
show(int timeout)
hide()
isShowing()
onTouchEvent()

show()
show(int timeout)
hide()
isShowing()
onTouchEvent()

All notes are in the code

所有注释都在代码中

public class ViewImageVideoFragment extends Fragment
{

   private int position = 0;
   private MediaController mMediaController;

   @Override
   public void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      mMediaController = new MediaController(getActivity());
   }

   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
   {

      if (savedInstanceState != null)
      {
         position = savedInstanceState.getInt("position");
      }

      v = inflater.inflate(R.layout.fragment_video_view, parent, false);

      mVideoView = (VideoView) v.findViewById(R.id.fragmentVideoView);
      mVideoView.setVideoPath(videoPath);
      mVideoView.setMediaController(mMediaController);

      mVideoView.setOnTouchListener(
            new View.OnTouchListener()
            {
               @Override
               public boolean onTouch(View v, MotionEvent motionEvent)
               {
                  if (mVideoView.isPlaying())
                  {
                     mVideoView.pause();


                  /*

                  Ok, so now you want to use that show(), preferrably without the int timeout

                  I didn't add it in myself but you should be able to handle it yourself

                  */

                     return true;
                  }
                  else /* I changed it to else, change it to if else if you have something specific you want to deal with */
                  {                                  

                  /* 

                  I would use that hide method I linked here, then start the 
                  video, I assume you know how to play the video yourself 

                  */

                  }

                  return false;
               }
            });

      mVideoView.seekTo(position);

      mVideoView.start();
   }

   @Override
   public void onSaveInstanceState(Bundle savedInstanceState)
   {
      super.onSaveInstanceState(savedInstanceState);

      if (mVideoView != null)
      {
         savedInstanceState.putInt("position", mVideoView.getCurrentPosition());
      }

      mVideoView.pause();
   }
}

I provided the other methods because, depending on how you may continue, they may or may not prevent future questions.

我提供了其他方法,因为根据您继续的方式,它们可能会也可能不会阻止未来的问题。