最好的答案是簡單地用一個TextureView而不是SurfaceView的(一個VideoView從SurfaceView默認繼承)。要做到這一點,使用的代碼如下:
定義您TextureView在activity_main.xml
:
<TextureView
android:id="@+id/videoTexture"
android:layout_width="match_parent"
android:layout_height="match_parent />
在你MainActivity.java
,聲明以下變量:
private MediaPlayer mMediaPlayer;
private TextureView mVideoTextureView;
private float mDisplayWidth;
private float mDisplayHeight;
然後在您的onCreate()
方法,對它們進行初始化如下:
mVideoTextureView =(TextureView) rootview.findViewById(R.id.videoTexture);
mVideoTextureView.setSurfaceTextureListener(this);
mMediaPlayer = new MediaPlayer();
loadNewMovie();
要加載影片到的MediaPlayer,請使用以下代碼:
private void loadNewMovie() {
AssetFileDescriptor afd = this.getResources().openRawResourceFd(ID_OF_YOUR_MOVIE);
try {
// Set source
mMediaPlayer.reset();
mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
mMediaPlayer.prepare();
/*
// Gets the Height/Width of the video but does NOT include space
// taken up by black bars if the dimensions don't exactly fit the screen.
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
String height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String width = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
mVideoHeight = Float.parseFloat(height);
mVideoWidth = Float.parseFloat(width);
*/
// Gets the size of the display in pixels (used for scaling)
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
mDisplayWidth = size.x;
mDisplayHeight = size.y;
// Play movie
if (currState == State.PLAYING)
mMediaPlayer.start();
afd.close();
}
catch (Exception e) {
Log.e("ERROR", "loadNewMovie: " + e.getMessage(), e);
}
mMediaPlayer.seekTo(DEFAULT_VIDEO_INIT_POSITION);
}
最後,您的視頻可以即時使用下面的代碼調整:
private void updateTextureViewSize(int viewWidth, int viewHeight) {
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(viewWidth,viewHeight);
// ANY OTHER RULES...EXAMPLE:
// params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mVideoTextureView.setLayoutParams(params);
}
或者你可以動畫這樣的變化:
private void animateTextureViewScaling(final float startScaleX, final float startScaleY,
final float endScaleX, final float endScaleY,
int duration) {
// Note: Can't just use .scaleX and .scaleY directly because it will only scale
// the video, not it's holder
mVideoTextureView.animate().setDuration(duration)
.setUpdateListener(new AnimatorUpdateListener() {
float value, scalingX, scalingY;
float changeXScale = startScaleX - endScaleX;
float changeYScale = startScaleY - endScaleY;
@Override
public void onAnimationUpdate(ValueAnimator animation) {
value = (Float) animation.getAnimatedValue();
scalingX = (float) (startScaleX - changeXScale*value);
scalingY = (float) (startScaleX - changeYScale*value);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
(int) (mDisplayWidth*scalingX), (int) (mDisplayHeight*scalingY));
// ANY OTHER RULES...EXAMPLE:
// params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
mVideoTextureView.setLayoutParams(params);
}
}).start();
}
在上面的代碼中,我用mDisplayWidth
(在loadNewVideo()
組)爲我視頻的原始大小。你可以使用任何你想要的。
好處這是一個TextureView可以動畫,轉換和縮放(SurfaceView不能)。
缺點是一個TextureView只能用於硬件加速窗口,並會比SurfaceView使用更多的內存(大約30%)。它也可能經歷1到3幀的延遲。
你錯過了這段代碼中的重要部分......(我認爲)。您還應該將MediaPlayer設置爲使用TextureView。可能在SurfaceTextureListener的onSurfaceTextureAvailable方法中。 –