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
VideoView onTouch events: pause/resume video, and show/hide MediaController and ActionBar
提问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 ActionBar
and the MediaController
. When the video is resumed, I'd like to hide the ActionBar
and MediaController
(possibly after a slight delay?)
当用户按下我的应用程序中的按钮时,他们会观看他们的视频。当他们第一次打开那个屏幕时,我希望视频暂停而不是立即播放。我还希望能够通过点击屏幕来暂停视频的播放。当视频暂停时,我想显示ActionBar
和MediaController
。当视频恢复时,我想隐藏ActionBar
和MediaController
(可能稍有延迟?)
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.
我已经尝试了一些方法,但最终还是遇到了问题,例如视频会暂停但无法恢复,或者ActionBar
和MediaController
无法正确显示或隐藏。
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.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. 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 Bitmap
which you can then throw in an ImageView
and 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.
我提供了其他方法,因为根据您继续的方式,它们可能会也可能不会阻止未来的问题。