简体   繁体   English

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

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

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的某种解决方案(需要返回错误),但我仍然不知道如何回答问题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 ActionBar and the MediaController . 当视频暂停时,我想显示ActionBarMediaController When the video is resumed, I'd like to hide the ActionBar and MediaController (possibly after a slight delay?) 当视频恢复时,我想隐藏ActionBarMediaController (可能会稍微延迟?)

I've tried a few things, but I end up with problems, like the video will pause but not resume, or the ActionBar and MediaController will 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. 我找到了问题1的部分解决方案,并更新了代码,以便在第一次打开时将视频显示为暂停。 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. 但我不知道如何在开始时绕过黑屏。

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();
    }
}

To first show the video as paused, simply change seekTo(0) to seekTo(1) in your code. 要首先将视频显示为暂停,只需在代码seekTo(0)更改为seekTo(1) This will move the video to the time at 1 millisecond and you can take it from there. 这会将视频移动到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();
}

} }

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.seekTo to move the video some frames ahead, for example using the value 150 to display the frame at the 150th millisecond in the video file. 您可以使用MediaPlayer.seekTo将视频向前移动一些帧,例如使用值150在视频文件中以150毫秒显示帧。 The video does not need to be started in order to seek. 视频无需启动即可查找。

MediaMetadataRetriever 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 Bitmap which you can then throw in an ImageView and set in place of the video. 这将为您提供一个Bitmap ,然后您可以将其放入ImageView并设置代替视频。 However, this API has always been buggy for me depending on the types of video codecs you are dealing with. 但是,根据您正在处理的视频编解码器的类型,此API一直是我的错误。

My sources -- 我的来源 -

show() 节目()
show(int timeout) show(int timeout)
hide() 隐藏()
isShowing() isShowing()
onTouchEvent() 的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. 我提供了其他方法,因为根据您的继续方式,他们可能会或可能不会预防未来的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM