2016-08-20 153 views
1

我有一个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

最好的答案是简单地用一个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帧的延迟。

+0

你错过了这段代码中的重要部分......(我认为)。您还应该将MediaPlayer设置为使用TextureView。可能在SurfaceTextureListener的onSurfaceTextureAvailable方法中。 –

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