add support for showing animated gifs in imagePreview
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / preview / ImageViewCustom.java
1 package com.owncloud.android.ui.preview;
2
3 import android.annotation.SuppressLint;
4 import android.content.Context;
5 import android.graphics.Bitmap;
6 import android.graphics.Canvas;
7 import android.graphics.Movie;
8 import android.os.Build;
9 import android.util.AttributeSet;
10 import android.view.View;
11 import android.widget.ImageView;
12
13 import com.owncloud.android.datamodel.OCFile;
14 import com.owncloud.android.lib.common.utils.Log_OC;
15
16 import java.io.FileInputStream;
17 import java.io.InputStream;
18
19 public class ImageViewCustom extends ImageView {
20
21 private static final String TAG = ImageViewCustom.class.getSimpleName();
22
23 private static final boolean IS_ICS_OR_HIGHER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
24 private static final boolean IS_VERSION_BUGGY_ON_RECYCLES =
25 Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR1 ||
26 Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2;
27
28 private int mBitmapHeight;
29 private int mBitmapWidth;
30
31 private Movie gifMovie;
32 private int movieWidth, movieHeight;
33 private long movieDuration;
34 private long movieRunDuration;
35 private long lastTick;
36
37 public ImageViewCustom(Context context) {
38 super(context);
39 }
40
41 public ImageViewCustom(Context context, AttributeSet attrs) {
42 super(context, attrs);
43 }
44
45 public ImageViewCustom(Context context, AttributeSet attrs, int defStyle) {
46 super(context, attrs, defStyle);
47 }
48
49 @SuppressLint("NewApi")
50 @Override
51 protected void onDraw(Canvas canvas) {
52 if(IS_ICS_OR_HIGHER && checkIfMaximumBitmapExceed(canvas) || IS_VERSION_BUGGY_ON_RECYCLES ) {
53 // Software type is set with two targets:
54 // 1. prevent that bitmaps larger than maximum textures allowed are shown as black views in devices
55 // with LAYER_TYPE_HARDWARE enabled by default;
56 // 2. grant that bitmaps are correctly de-allocated from memory in versions suffering the bug fixed in
57 // https://android.googlesource.com/platform/frameworks/base/+/034de6b1ec561797a2422314e6ef03e3cd3e08e0;
58 //
59 setLayerType(View.LAYER_TYPE_SOFTWARE, null);
60 }
61
62 if(gifMovie == null){
63 super.onDraw(canvas);
64 } else {
65 long nowTick = android.os.SystemClock.uptimeMillis();
66 if (lastTick == 0) {
67 movieRunDuration = 0;
68 } else {
69 movieRunDuration += nowTick -lastTick;
70 if(movieRunDuration > movieDuration){
71 movieRunDuration = 0;
72 }
73 }
74
75 gifMovie.setTime((int) movieRunDuration);
76
77 float scale;
78 if(gifMovie.height() > getHeight() || gifMovie.width() > getWidth()) {
79 scale = (1f / Math.min(canvas.getHeight() / gifMovie.height(),
80 canvas.getWidth() / gifMovie.width())) + 0.25f;
81 } else {
82 scale = Math.min(canvas.getHeight() / gifMovie.height(),
83 canvas.getWidth() / gifMovie.width());
84 }
85
86 canvas.scale(scale, scale);
87 canvas.translate(((float) getWidth() / scale - (float) gifMovie.width()) / 2f,
88 ((float) getHeight() / scale - (float) gifMovie.height()) /2f);
89
90 gifMovie.draw(canvas, 0, 0);
91
92 lastTick = nowTick;
93 invalidate();
94 }
95 }
96
97 @Override
98 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
99 setMeasuredDimension(movieWidth, movieHeight);
100 }
101
102 /**
103 * Checks if current bitmaps exceed the maximum OpenGL texture size limit
104 * @param canvas Canvas where the view will be drawn into.
105 * @return boolean True means that the bitmap is too big for the canvas.
106 */
107 @SuppressLint("NewApi")
108 private boolean checkIfMaximumBitmapExceed(Canvas canvas) {
109 return mBitmapWidth > canvas.getMaximumBitmapWidth()
110 || mBitmapHeight > canvas.getMaximumBitmapHeight();
111
112 }
113
114 @Override
115 /**
116 * Keeps the size of the bitmap cached in member variables for faster access in {@link #onDraw(Canvas)} ,
117 * but without keeping another reference to the {@link Bitmap}
118 */
119 public void setImageBitmap(Bitmap bm) {
120 mBitmapWidth = bm.getWidth();
121 mBitmapHeight = bm.getHeight();
122 super.setImageBitmap(bm);
123 }
124
125 public void setGifImage(OCFile file){
126 try {
127 InputStream gifInputStream = new FileInputStream(file.getStoragePath());
128 setLayerType(View.LAYER_TYPE_SOFTWARE, null);
129 setFocusable(true);
130
131 gifMovie = Movie.decodeStream(gifInputStream);
132 movieWidth = gifMovie.width();
133 movieHeight = gifMovie.height();
134 movieDuration = gifMovie.duration();
135 } catch (Exception e) {
136 e.printStackTrace();
137 }
138 }
139
140 }