【问题标题】:How Can I Animate Changing the Size of a VideoView?如何动画更改 VideoView 的大小?
【发布时间】:2016-08-20 01:02:45
【问题描述】:

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

非常感谢任何帮助!

【问题讨论】:

    标签: android animation transition android-videoview


    【解决方案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();
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 您在此代码中缺少一个重要部分...(我认为)。您还应该将 MediaPlayer 设置为使用 TextureView。可能在 SurfaceTextureListener 的 onSurfaceTextureAvailable 方法中..
      猜你喜欢
      • 2014-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-05
      • 2020-05-04
      • 1970-01-01
      • 2019-02-13
      相关资源
      最近更新 更多