diff --git a/src/com/owncloud/android/ui/preview/ImageViewCustom.java b/src/com/owncloud/android/ui/preview/ImageViewCustom.java index 69182d6e0b..f4e808bf6d 100644 --- a/src/com/owncloud/android/ui/preview/ImageViewCustom.java +++ b/src/com/owncloud/android/ui/preview/ImageViewCustom.java @@ -4,13 +4,18 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Movie; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; +import java.io.FileInputStream; +import java.io.InputStream; + public class ImageViewCustom extends ImageView { private static final String TAG = ImageViewCustom.class.getSimpleName(); @@ -23,7 +28,12 @@ public class ImageViewCustom extends ImageView { private int mBitmapHeight; private int mBitmapWidth; - + private Movie mGifMovie; + private int mMovieWidth, mMovieHeight; + private long mMovieDuration; + private long mMovieRunDuration; + private long mLastTick; + public ImageViewCustom(Context context) { super(context); } @@ -39,18 +49,60 @@ public class ImageViewCustom extends ImageView { @SuppressLint("NewApi") @Override protected void onDraw(Canvas canvas) { - if(IS_ICS_OR_HIGHER && checkIfMaximumBitmapExceed(canvas) || IS_VERSION_BUGGY_ON_RECYCLES ) { // Software type is set with two targets: // 1. prevent that bitmaps larger than maximum textures allowed are shown as black views in devices // with LAYER_TYPE_HARDWARE enabled by default; - // 2. grant that bitmaps are correctly dellocated from memory in versions suffering the bug fixed in + // 2. grant that bitmaps are correctly de-allocated from memory in versions suffering the bug fixed in // https://android.googlesource.com/platform/frameworks/base/+/034de6b1ec561797a2422314e6ef03e3cd3e08e0; // setLayerType(View.LAYER_TYPE_SOFTWARE, null); } - super.onDraw(canvas); + if(mGifMovie != null) { + long nowTick = android.os.SystemClock.uptimeMillis(); + if (mLastTick == 0) { + mMovieRunDuration = 0; + } else { + mMovieRunDuration += nowTick - mLastTick; + if(mMovieRunDuration > mMovieDuration) { + mMovieRunDuration = 0; + } + } + + mGifMovie.setTime((int) mMovieRunDuration); + + float scale = getScaleToViewFactor(mGifMovie, canvas); + + canvas.scale(scale, scale); + canvas.translate(((float) getWidth() / scale - (float) mGifMovie.width()) / 2f, + ((float) getHeight() / scale - (float) mGifMovie.height()) /2f); + + mGifMovie.draw(canvas, 0, 0); + + mLastTick = nowTick; + invalidate(); + } else { + super.onDraw(canvas); + } + } + + private float getScaleToViewFactor(Movie movie, Canvas canvas) { + if (movie.height() > getHeight() || movie.width() > getWidth()) { + float offset = 0.25f; + return (1f / Math.min(canvas.getHeight() / movie.height(), canvas.getWidth() / movie.width())) + offset; + } + + return Math.min(canvas.getHeight() / movie.height(), canvas.getWidth() / movie.width()); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mGifMovie == null) { + setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); + } else { + setMeasuredDimension(mMovieWidth, mMovieHeight); + } } /** @@ -60,24 +112,40 @@ public class ImageViewCustom extends ImageView { */ @SuppressLint("NewApi") private boolean checkIfMaximumBitmapExceed(Canvas canvas) { - Log_OC.v(TAG, "Canvas maximum: " + canvas.getMaximumBitmapWidth() + " - " + canvas.getMaximumBitmapHeight()); - if (mBitmapWidth > canvas.getMaximumBitmapWidth() - || mBitmapHeight > canvas.getMaximumBitmapHeight()) { - return true; - } - - return false; + return mBitmapWidth > canvas.getMaximumBitmapWidth() + || mBitmapHeight > canvas.getMaximumBitmapHeight(); + } @Override /** - * Keeps the size of the bitmap cached in member variables for faster access in {@link #onDraw(Canvas)} , + * Keeps the size of the bitmap cached in member variables for faster access in {@link #onDraw(Canvas)}, * but without keeping another reference to the {@link Bitmap} */ - public void setImageBitmap (Bitmap bm) { + public void setImageBitmap(Bitmap bm) { mBitmapWidth = bm.getWidth(); mBitmapHeight = bm.getHeight(); super.setImageBitmap(bm); } + /** + * sets the GIF image of the given storage path. + * + * @param storagePath the storage path of the GIF image + */ + public void setGIFImageFromStoragePath(String storagePath) { + try { + InputStream gifInputStream = new FileInputStream(storagePath); + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + setFocusable(true); + + mGifMovie = Movie.decodeStream(gifInputStream); + mMovieWidth = mGifMovie.width(); + mMovieHeight = mGifMovie.height(); + mMovieDuration = mGifMovie.duration(); + } catch (Exception e) { + Log_OC.e(TAG, "Failed to set GIF image"); + } + } + } diff --git a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java index da5be22d04..9bfcc91804 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java @@ -499,12 +499,17 @@ public class PreviewImageFragment extends FileFragment { Log_OC.d(TAG, "Showing image with resolution " + bitmap.getWidth() + "x" + bitmap.getHeight()); - if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")){ + if (result.ocFile.getMimetype().equalsIgnoreCase("image/png")) { Drawable backrepeat = getResources().getDrawable(R.drawable.backrepeat); imageView.setBackground(backrepeat); } - imageView.setImageBitmap(bitmap); + if (result.ocFile.getMimetype().equalsIgnoreCase("image/gif")) { + imageView.setGIFImageFromStoragePath(result.ocFile.getStoragePath()); + } else { + imageView.setImageBitmap(bitmap); + } + imageView.setVisibility(View.VISIBLE); mBitmap = bitmap; // needs to be kept for recycling when not useful }