Как я могу анимировать изменение размера VideoView?
У меня есть VideoView, который я хочу динамически изменять размер в моем приложении. Расширяя класс VideoView, я успешно получил и video, и 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);
Любая помощь высоко ценится!
2 ответа
Лучший ответ - просто использовать 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 можно использовать только в окне с аппаратным ускорением и использовать гораздо больше памяти (около 30%), чем SurfaceView. Также может наблюдаться задержка от 1 до 3 кадров.
Одно решение, которое я нашел, состоит в том, чтобы использовать 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();