2016-08-20 144 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();