【问题标题】:Cannot scale gif move frame in Android Canvas无法在 Android Canvas 中缩放 gif 移动帧
【发布时间】:2012-07-28 16:34:30
【问题描述】:

我在缩放 GIF 影片帧时遇到问题。我在绘制框架之前使用 Canvas.scale(float sx, float sy) 。但它不绘制缩放框架,它什么也不画。有什么想法吗?

【问题讨论】:

  • 你应该先画draw gif,然后缩放画布。

标签: android scale android-canvas gif


【解决方案1】:

如果您尝试在另一个布局中创建可缩放和可重用的专用视图,您也应该使用视图的 getWidth() 和 getHeight() 方法。

我在更改 View 的专用尺寸时遇到了这个问题:canvas.getWidth() 是整个屏幕的宽度,而不是视图的宽度,所以我修改了 onDraw 方法如下。

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(Color.TRANSPARENT);
    super.onDraw(canvas);

    long now = android.os.SystemClock.uptimeMillis();  

    Paint p = new Paint();
    p.setAntiAlias(true);

    if (cur == 0) cur = now;  

    if(movie != null)
    {
        float scale = 1f;
        if(movie.height() > getHeight() || movie.width() > getWidth())
            scale = ( 1f / Math.min(canvas.getHeight() / movie.height(), canvas.getWidth() / movie.width()) ) + 0.25f;
        else    
            scale = Math.min(canvas.getHeight() / movie.height(), canvas.getWidth() / movie.width());

        canvas.scale(scale, scale);
        canvas.translate(((float)getWidth() / scale - (float)movie.width())/2f,
                ((float)getHeight() / scale - (float)movie.height())/2f);

        int relTime = (int)((now - cur) % movie.duration());
        movie.setTime(relTime);
        movie.draw(canvas, 0, 0);


        invalidate();
    }
}

注意 getWidth(), getHeight() if 语句检查电影是否大于视图,在我的情况下,我的视图高度是 160,但我的 GIF 是 260,但是使用其他方法它总是会绘制GIF 太大了,通过这些更改,我能够测试并看到它在我的视图为 1280 X 900 并且图像放大的情况下以及我的视图为 1000 X 160 并且它缩小的情况下都能正常工作。

祝你好运,玩得开心:D

-克里斯

【讨论】:

  • 我发现只在绘图代码中使用'else'语句会产生更好的结果——即。它扩展到所有设备。我在我的项目中取消了“if”语句。
【解决方案2】:

这应该可行。

protected void onDraw(Canvas canvas)
{
    canvas.drawColor(Color.TRANSPARENT);

    canvas.scale(0.5f, 0.5f); // scale gif to its half size

    super.onDraw(canvas);

    /* movie.setTime . . . */

    movie.draw(canvas, ...);

    this.invalidate();

}

【讨论】:

    【解决方案3】:

    这是我的解决方案:

    public class GifImageView extends View {
        private InputStream mInputStream;
        private Movie mMovie;
        public int mWidth, mHeight;
        private long mStart;
        private Context mContext;
    
        public GifImageView(Context context) {
            super(context);
            this.mContext = context;
        }
    
        public GifImageView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public GifImageView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.mContext = context;
            if (attrs.getAttributeName(1).equals("background")) {
                int id = Integer.parseInt(attrs.getAttributeValue(1).substring(1));
                setGifImageResource(id);
            }
        }
    
        private void init() {
            setFocusable(true);
            mMovie = Movie.decodeStream(mInputStream);
            mWidth = mMovie.width();
            mHeight = mMovie.height();
    
            requestLayout();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(mWidth, mHeight);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            long now = SystemClock.uptimeMillis();
    
            if (mStart == 0) {
                mStart = now;
            }
    
            if (mMovie != null) {
                int duration = mMovie.duration();
                if (duration == 0) {
                    duration = 1000;
                }
    
                float scale = Math.min((float) canvas.getHeight() / (float) mMovie.height(), (float) canvas.getWidth() / (float) mMovie.width());
    
                canvas.scale(scale, scale);
                canvas.translate(((float) mWidth / scale - (float) mMovie.width()) / 2f,
                    ((float) mHeight / scale - (float) mMovie.height()) / 2f);
    
                int relTime = (int) ((now - mStart) % duration);
    
                mMovie.setTime(relTime);
                mMovie.draw(canvas, 0, 0);
                invalidate();
            }
        }
    
        public void setGifImageResource(int id) {
            mInputStream = mContext.getResources().openRawResource(id);
            init();
        }
    
        public void setGifImageUri(Uri uri) {
            try {
                mInputStream = mContext.getContentResolver().openInputStream(uri);
                init();
            } catch (FileNotFoundException e) {
                Log.e("GIfImageView", "File not found");
            }
        }
    
        public void setSize(int dimension) {
            mWidth = dimension;
            mHeight = dimension;
        }
    }
    

    将其添加到您的布局文件中:

    <GifImageView
            android:id="@+id/gifView"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerHorizontal="true"
            android:background="@drawable/image" />
    

    那么您可以在 Java 代码中简单地设置维度:

    gifView.setSize(dimension);
    

    【讨论】:

      【解决方案4】:

      此示例允许我们将 GIF以适应屏幕调整为图像的原始尺寸。

      PlayGifView.class

      public class PlayGifView extends View{
      
          private static final int DEFAULT_MOVIEW_DURATION = 1000;
      
          private int mMovieResourceId;
          private Movie mMovie;
      
          private long mMovieStart = 0;
          private int mCurrentAnimationTime = 0;
      public Context context;
          @SuppressLint("NewApi")
          public PlayGifView(Context context, AttributeSet attrs) {
              super(context, attrs);
              this.context = context;
             /**
              * Starting from HONEYCOMB have to turn off HardWare acceleration to draw
              * Movie on Canvas.
              */
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                 setLayerType(View.LAYER_TYPE_SOFTWARE, null);
             }
      
         }
      
          public void setImageResource(int mvId){
              this.mMovieResourceId = mvId;
             mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));
             requestLayout();
          }
      
          public void setMovieData(Movie movieImg){
              mMovie = movieImg;
              requestLayout();
          }
      
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if(mMovie != null){
      
             //Find higest
             int exceptedSize = 200;
             int highest = 0;
             int quality = 0;
             if(mMovie.height()>mMovie.width()){
                 highest=mMovie.height();
             }else{
                 highest=mMovie.width();
             }
      
             //Get Display Size
             Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
             Point size = new Point();
             display.getSize(size);
      
             setMeasuredDimension((int)(((float)mMovie.width()/(float)highest)*((float) size.x))
                     , (int)(((float)mMovie.height()/(float)highest)*((float)size.x)));
         }else{
             setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
         }
      }
      
      @Override
      protected void onDraw(Canvas canvas) {
         if (mMovie != null){
             updateAnimtionTime();
      
             //Get Display Size
             Display display = ((Activity) getContext()).getWindowManager().getDefaultDisplay();
             Point size = new Point();
             display.getSize(size);
      
             float scale = Math.max((float) canvas.getHeight() / (float) mMovie.height(), (float) canvas.getWidth() / (float) mMovie.width());
      
             canvas.scale(scale, scale);
             canvas.translate(((float) size.x / scale - (float) mMovie.width()) / 2f,
                     0);
      
             drawGif(canvas);
             invalidate();
         }else{
      //       drawGif(canvas);
         }
      }
      
      private void updateAnimtionTime() {
         long now = android.os.SystemClock.uptimeMillis();
      
         if (mMovieStart == 0) {
             mMovieStart = now;
         }
         int dur = mMovie.duration();
         if (dur == 0) {
             dur = DEFAULT_MOVIEW_DURATION;
         }
         mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
      }
      
      private void drawGif(Canvas canvas) {
         mMovie.setTime(mCurrentAnimationTime);
         mMovie.draw(canvas, 0, 0);
         canvas.restore();
      }
      
      }
      

      Main Activity.class

      PlayGifView pGif = findViewById(R.id.viewGif);
      pGif.setImageResource(R.drawable.ads1);
      

      activity_main.xml

      <com.---- Yours-----.PlayGifView
          android:id="@+id/viewGif"
          android:gravity="center"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-16
        • 1970-01-01
        • 2013-06-30
        • 2019-09-02
        • 2014-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多