我有一个VideoView,我想在我的应用中动态更改大小。通过扩展VideoView类,我成功地获得了视频和videoView以正确地改变大小。但是,我希望能够逐渐在两种尺寸之间进行转换。我怎样才能做到这一点?我尝试过缩放动画,但是虽然这会改变VideoView布局的大小,但视频本身并没有缩放。想法?
这是我的视频课程:
public class MyVideoView extends VideoView {
private int mForceHeight,mForceWidth;
private int mOrigWidth, mOrigHeight, mMinWidth, mMinHeight;
public MyVideoView(Context context) {
super(context);
}
/* Will cause inflator errors if not present */
public MyVideoView(Context context, AttributeSet attrs){
super(context, attrs);
}
public void setDimensions(int w, int h) {
this.mForceHeight = h;
this.mForceWidth = w;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mForceHeight != 0)
setMeasuredDimension(mForceWidth, mForceHeight);
else
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void setOrigDimens(int width, int height) {
mOrigWidth = width;
mOrigHeight = height;
mMinWidth = width/4; // My own decision for the small size
mMinHeight = height/4;
}
public void setSmallView() {
setNewViewSize(mMinWidth, mMinHeight);
}
public void setNormalView() {
setNewViewSize(mOrigWidth, mOrigHeight);
}
/* RESIZES THE VIEW */
public void setNewViewSize(int width, int height) {
mForceWidth = width;
mForceHeight = height;
setDimensions(width, height);
getHolder().setFixedSize(width, height);
}
}
这是我尝试过的缩放代码:
Animation scaling = new ScaleAnimation(1.0f, 0.2f, 1.0f, 0.2f);
scaling.setDuration(2000);
startAnimation(scaling);
非常感谢任何帮助!
答案 0 :(得分:1)
我找到的一个解决方案是使用ValueAnimator更改大小应该是的比率,然后使用更新侦听器强制视频实际更改大小。然而,它非常紧张:
ValueAnimator scaleDown = ValueAnimator.ofFloat(1, 0.25f);
scaleDown.setDuration(1000);
scaleDown.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float) animation.getAnimatedValue();
setNewViewSize(mOrigWidth*value, mOrigHeight*value);
}
});
scaleDown.start();
答案 1 :(得分:0)
最佳答案是简单地使用 TextureView 而不是SurfaceView(默认情况下VideoView继承自SurfaceView)。为此,请使用以下代码:
在activity_main.xml
中定义TextureView:
<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帧延迟。