react-native-fast-image 8.20.0 → 8.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/android/src/main/java/com/dylanvann/fastimage/FastImageBlur.java +213 -0
- package/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java +6 -1
- package/android/src/main/java/com/dylanvann/fastimage/FastImageSourceSize.java +17 -2
- package/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java +21 -0
- package/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java +287 -12
- package/dist/index.cjs.js +15 -1
- package/dist/index.cjs.js.flow +8 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +15 -1
- package/dist/index.js.flow +8 -0
- package/ios/FastImage/FFFastImageView.h +8 -0
- package/ios/FastImage/FFFastImageView.m +324 -17
- package/ios/FastImage/FFFastImageViewManager.m +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,6 +212,27 @@ Pauses an animated image (GIF, and animated WebP on iOS) on the frame it's showi
|
|
|
212
212
|
|
|
213
213
|
---
|
|
214
214
|
|
|
215
|
+
### `transition?: boolean | number | Transition`
|
|
216
|
+
|
|
217
|
+
Fades the image in when it loads. Off by default. `true` uses the platform's usual fade, a number is the duration in milliseconds, or pass an object:
|
|
218
|
+
|
|
219
|
+
- `duration`: milliseconds; 0 is no fade. Defaults to the platform's usual length: 300 ms on Android, 250 ms on iOS.
|
|
220
|
+
- `betweenImages` (default `false`): also fade between images. By default an image fades in when it appears over nothing (or over `defaultSource`), and a new `source` replaces the image that's showing at once, once it has loaded. With `true`, the new image cross-dissolves from the one showing (for a gallery or an avatar that changes, say).
|
|
221
|
+
- `skipOnCacheHit`: which images show at once, without the fade:
|
|
222
|
+
- `'memory'` (default): images from the memory cache, so a list scrolled back up shows images it already loaded at once. Images from the disk cache fade in.
|
|
223
|
+
- `'all'`: images from the memory or disk cache: images that download fade in, and local files and bundled images usually only the first time they load (the disk cache usually keeps them too).
|
|
224
|
+
- `'none'`: every image fades in.
|
|
225
|
+
|
|
226
|
+
Downloads, local files (`file://`, `content://`) and bundled images (`require()`) fade in. In lists that reuse views (e.g. FlashList), set `recyclingKey`, so a reused view starts empty and its image fades in, instead of showing the previous item's image until it loads.
|
|
227
|
+
|
|
228
|
+
```jsx
|
|
229
|
+
<FastImage source={{ uri }} transition />
|
|
230
|
+
<FastImage source={{ uri }} transition={500} />
|
|
231
|
+
<FastImage source={{ uri }} transition={{ betweenImages: true, skipOnCacheHit: 'none' }} />
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
215
236
|
### `downsample?: boolean`
|
|
216
237
|
|
|
217
238
|
iOS only. Decodes a large image at about the size it's shown at, instead of at full size, so it takes much less memory.
|
|
@@ -222,6 +243,22 @@ Decoding a smaller copy can take a little longer, so use it where the memory mat
|
|
|
222
243
|
|
|
223
244
|
---
|
|
224
245
|
|
|
246
|
+
### `blurRadius?: number`
|
|
247
|
+
|
|
248
|
+
Blurs the image by this radius, in points, like React Native's `Image` (the same radius looks about the same on iOS and Android). `0` **(Default)** is no blur.
|
|
249
|
+
|
|
250
|
+
It's for still images, or a radius that changes now and then (e.g. blurring a photo behind a sheet). Each change blurs the image again on the CPU, so don't animate it.
|
|
251
|
+
|
|
252
|
+
- Only the loaded image is blurred, not `defaultSource`.
|
|
253
|
+
- An animated image (GIF, animated WebP) shows its first frame, blurred, and doesn't animate.
|
|
254
|
+
- With `tintColor`, the blurred image is tinted.
|
|
255
|
+
- The image is blurred at about the size it's shown at, off the main thread. The cached file stays the original image, so `getCachePath` and other views of it aren't affected.
|
|
256
|
+
- Changing it blurs the image that's showing again, without sending the load events again.
|
|
257
|
+
|
|
258
|
+
To animate a blur, or to blur an animated image, use React Native's `filter` style instead, which the GPU draws: `style={{ filter: [{ blur: 6 }] }}`. It needs the New Architecture. React Native's docs list `blur` for Android 12+ only; on iOS it's behind an experimental React Native feature flag (`enableSwiftUIBasedFilters`, SwiftUI-based filters).
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
225
262
|
### `onLoadStart?: () => void`
|
|
226
263
|
|
|
227
264
|
Called when the image starts to load.
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
package com.dylanvann.fastimage;
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap;
|
|
4
|
+
import android.graphics.Canvas;
|
|
5
|
+
import android.graphics.Paint;
|
|
6
|
+
import android.graphics.PorterDuff;
|
|
7
|
+
import android.graphics.PorterDuffXfermode;
|
|
8
|
+
import android.widget.ImageView;
|
|
9
|
+
|
|
10
|
+
import androidx.annotation.NonNull;
|
|
11
|
+
|
|
12
|
+
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
|
|
13
|
+
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
|
|
14
|
+
import com.bumptech.glide.request.target.Target;
|
|
15
|
+
|
|
16
|
+
import java.nio.IntBuffer;
|
|
17
|
+
import java.nio.charset.Charset;
|
|
18
|
+
import java.security.MessageDigest;
|
|
19
|
+
|
|
20
|
+
// Blurs the image (blurRadius), as React Native's Image does on iOS: three box
|
|
21
|
+
// blurs, close to a Gaussian blur, with the box size worked out from the radius
|
|
22
|
+
// (in pixels) as the SVG spec describes and halved, as React Native does. So a
|
|
23
|
+
// radius looks the same on both platforms. It runs after the scale type's crop
|
|
24
|
+
// or fit, on the image at about the size the view shows it (a blurred image
|
|
25
|
+
// needs no more detail), on Glide's threads. Part of the request's key, so
|
|
26
|
+
// blurred and unblurred views of one image don't share a cached image; the
|
|
27
|
+
// cached file stays the original.
|
|
28
|
+
final class FastImageBlur extends BitmapTransformation {
|
|
29
|
+
private static final String ID = "com.dylanvann.fastimage.FastImageBlur";
|
|
30
|
+
private static final byte[] ID_BYTES = ID.getBytes(Charset.forName("UTF-8"));
|
|
31
|
+
|
|
32
|
+
// In pixels on screen.
|
|
33
|
+
private final float radius;
|
|
34
|
+
private final ImageView.ScaleType scaleType;
|
|
35
|
+
|
|
36
|
+
FastImageBlur(float radius, ImageView.ScaleType scaleType) {
|
|
37
|
+
this.radius = radius;
|
|
38
|
+
this.scaleType = scaleType;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Override
|
|
42
|
+
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
|
|
43
|
+
int width = toTransform.getWidth();
|
|
44
|
+
int height = toTransform.getHeight();
|
|
45
|
+
if (outWidth == Target.SIZE_ORIGINAL) outWidth = width;
|
|
46
|
+
if (outHeight == Target.SIZE_ORIGINAL) outHeight = height;
|
|
47
|
+
// How many pixels on screen a pixel of the bitmap takes.
|
|
48
|
+
float shownScale = shownScale(width, height, outWidth, outHeight);
|
|
49
|
+
// Blurred at the size it's shown at, or at its own size if it's shown
|
|
50
|
+
// larger.
|
|
51
|
+
float scale = Math.min(shownScale, 1);
|
|
52
|
+
int blurredWidth = Math.max(1, Math.round(width * scale));
|
|
53
|
+
int blurredHeight = Math.max(1, Math.round(height * scale));
|
|
54
|
+
int boxSize = boxSize(radius * scale / shownScale, Math.max(blurredWidth, blurredHeight));
|
|
55
|
+
if (boxSize <= 1 && scale == 1) return toTransform;
|
|
56
|
+
|
|
57
|
+
Bitmap result = pool.get(blurredWidth, blurredHeight, Bitmap.Config.ARGB_8888);
|
|
58
|
+
result.setDensity(toTransform.getDensity());
|
|
59
|
+
Canvas canvas = new Canvas(result);
|
|
60
|
+
canvas.scale(blurredWidth / (float) width, blurredHeight / (float) height);
|
|
61
|
+
canvas.drawBitmap(toTransform, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
|
|
62
|
+
canvas.setBitmap(null);
|
|
63
|
+
if (boxSize > 1) blur(pool, result, boxSize);
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Pixels on screen per pixel of the bitmap, for the view's scale type.
|
|
68
|
+
private float shownScale(int width, int height, int outWidth, int outHeight) {
|
|
69
|
+
if (width <= 0 || height <= 0 || outWidth <= 0 || outHeight <= 0) return 1;
|
|
70
|
+
float x = outWidth / (float) width;
|
|
71
|
+
float y = outHeight / (float) height;
|
|
72
|
+
if (scaleType == null) return 1;
|
|
73
|
+
switch (scaleType) {
|
|
74
|
+
case CENTER_CROP:
|
|
75
|
+
return Math.max(x, y);
|
|
76
|
+
case FIT_CENTER:
|
|
77
|
+
case FIT_START:
|
|
78
|
+
case FIT_END:
|
|
79
|
+
return Math.min(x, y);
|
|
80
|
+
case FIT_XY:
|
|
81
|
+
return (float) Math.sqrt(x * y);
|
|
82
|
+
case CENTER_INSIDE:
|
|
83
|
+
return Math.min(Math.min(x, y), 1);
|
|
84
|
+
default:
|
|
85
|
+
return 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// React Native's (RCTImageBlurUtils) for a radius in pixels: odd, so it's
|
|
90
|
+
// centered. At most the image's larger side (a larger box looks the same,
|
|
91
|
+
// and an absurd radius would overflow).
|
|
92
|
+
private static int boxSize(float radius, int max) {
|
|
93
|
+
double size = Math.floor((radius * 3 * Math.sqrt(2 * Math.PI) / 4 + 0.5) / 2);
|
|
94
|
+
return (int) Math.min(size, max) | 1;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Blurs the bitmap, on its premultiplied pixels (as stored), each byte a
|
|
98
|
+
// channel. A large box blurs a copy 2, 4 or 8 times smaller instead (each
|
|
99
|
+
// pixel the average of a block), with a box that much smaller, of at least
|
|
100
|
+
// 11 pixels, drawn back at full size: away from the edges that matches
|
|
101
|
+
// blurring at full size within a few levels of 255 (about as much as a
|
|
102
|
+
// slightly different radius changes it), for a quarter to a sixty-fourth of
|
|
103
|
+
// the work.
|
|
104
|
+
private static void blur(BitmapPool pool, Bitmap bitmap, int boxSize) {
|
|
105
|
+
int width = bitmap.getWidth();
|
|
106
|
+
int height = bitmap.getHeight();
|
|
107
|
+
int[] pixels = new int[width * height];
|
|
108
|
+
IntBuffer buffer = IntBuffer.wrap(pixels);
|
|
109
|
+
bitmap.copyPixelsToBuffer(buffer);
|
|
110
|
+
int factor = boxSize >= 88 ? 8 : boxSize >= 44 ? 4 : boxSize >= 22 ? 2 : 1;
|
|
111
|
+
if (factor == 1) {
|
|
112
|
+
blur(pixels, width, height, boxSize);
|
|
113
|
+
buffer.rewind();
|
|
114
|
+
bitmap.copyPixelsFromBuffer(buffer);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
int smallWidth = (width + factor - 1) / factor;
|
|
118
|
+
int smallHeight = (height + factor - 1) / factor;
|
|
119
|
+
int[] small = shrink(pixels, width, height, factor, smallWidth, smallHeight);
|
|
120
|
+
blur(small, smallWidth, smallHeight, Math.round((boxSize / (float) factor - 1) / 2) * 2 + 1);
|
|
121
|
+
Bitmap copy = pool.get(smallWidth, smallHeight, Bitmap.Config.ARGB_8888);
|
|
122
|
+
copy.copyPixelsFromBuffer(IntBuffer.wrap(small));
|
|
123
|
+
Canvas canvas = new Canvas(bitmap);
|
|
124
|
+
canvas.scale(factor, factor);
|
|
125
|
+
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
|
|
126
|
+
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
|
|
127
|
+
canvas.drawBitmap(copy, 0, 0, paint);
|
|
128
|
+
canvas.setBitmap(null);
|
|
129
|
+
pool.put(copy);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Three box blurs, each across then down, with the edges extended.
|
|
133
|
+
private static void blur(int[] pixels, int width, int height, int boxSize) {
|
|
134
|
+
int[] other = new int[width * height];
|
|
135
|
+
int radius = boxSize / 2;
|
|
136
|
+
for (int i = 0; i < 3; i++) {
|
|
137
|
+
for (int y = 0; y < height; y++) boxBlur(pixels, other, y * width, 1, width, radius);
|
|
138
|
+
for (int x = 0; x < width; x++) boxBlur(other, pixels, x, width, height, radius);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// A copy factor times smaller: each pixel the average of a factor × factor
|
|
143
|
+
// block (smaller at the right and bottom edges).
|
|
144
|
+
private static int[] shrink(int[] pixels, int width, int height, int factor, int smallWidth, int smallHeight) {
|
|
145
|
+
int[] small = new int[smallWidth * smallHeight];
|
|
146
|
+
for (int sy = 0; sy < smallHeight; sy++) {
|
|
147
|
+
for (int sx = 0; sx < smallWidth; sx++) {
|
|
148
|
+
int a = 0, b = 0, c = 0, d = 0, n = 0;
|
|
149
|
+
for (int y = sy * factor; y < Math.min(height, (sy + 1) * factor); y++) {
|
|
150
|
+
for (int x = sx * factor; x < Math.min(width, (sx + 1) * factor); x++) {
|
|
151
|
+
int pixel = pixels[y * width + x];
|
|
152
|
+
a += pixel >>> 24;
|
|
153
|
+
b += (pixel >> 16) & 0xff;
|
|
154
|
+
c += (pixel >> 8) & 0xff;
|
|
155
|
+
d += pixel & 0xff;
|
|
156
|
+
n++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
int half = n / 2;
|
|
160
|
+
small[sy * smallWidth + sx] = ((a + half) / n) << 24 | ((b + half) / n) << 16
|
|
161
|
+
| ((c + half) / n) << 8 | ((d + half) / n);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return small;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Averages each pixel of a row or column (count pixels from start, step
|
|
168
|
+
// apart) with the radius pixels on each side.
|
|
169
|
+
private static void boxBlur(int[] from, int[] to, int start, int step, int count, int radius) {
|
|
170
|
+
int size = 2 * radius + 1;
|
|
171
|
+
int half = size / 2;
|
|
172
|
+
int a = 0, b = 0, c = 0, d = 0;
|
|
173
|
+
for (int i = -radius; i <= radius; i++) {
|
|
174
|
+
int pixel = from[start + clamp(i, count) * step];
|
|
175
|
+
a += pixel >>> 24;
|
|
176
|
+
b += (pixel >> 16) & 0xff;
|
|
177
|
+
c += (pixel >> 8) & 0xff;
|
|
178
|
+
d += pixel & 0xff;
|
|
179
|
+
}
|
|
180
|
+
for (int i = 0; i < count; i++) {
|
|
181
|
+
to[start + i * step] = ((a + half) / size) << 24 | ((b + half) / size) << 16
|
|
182
|
+
| ((c + half) / size) << 8 | ((d + half) / size);
|
|
183
|
+
int added = from[start + clamp(i + radius + 1, count) * step];
|
|
184
|
+
int removed = from[start + clamp(i - radius, count) * step];
|
|
185
|
+
a += (added >>> 24) - (removed >>> 24);
|
|
186
|
+
b += ((added >> 16) & 0xff) - ((removed >> 16) & 0xff);
|
|
187
|
+
c += ((added >> 8) & 0xff) - ((removed >> 8) & 0xff);
|
|
188
|
+
d += (added & 0xff) - (removed & 0xff);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private static int clamp(int i, int count) {
|
|
193
|
+
return i < 0 ? 0 : i >= count ? count - 1 : i;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@Override
|
|
197
|
+
public boolean equals(Object o) {
|
|
198
|
+
return o instanceof FastImageBlur
|
|
199
|
+
&& ((FastImageBlur) o).radius == radius
|
|
200
|
+
&& ((FastImageBlur) o).scaleType == scaleType;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@Override
|
|
204
|
+
public int hashCode() {
|
|
205
|
+
return ID.hashCode() * 31 + Float.floatToIntBits(radius) * 31 + (scaleType == null ? 0 : scaleType.ordinal());
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@Override
|
|
209
|
+
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
|
|
210
|
+
messageDigest.update(ID_BYTES);
|
|
211
|
+
messageDigest.update((radius + "," + scaleType).getBytes(Charset.forName("UTF-8")));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -34,7 +34,12 @@ public class FastImageRequestListener implements RequestListener<Drawable> {
|
|
|
34
34
|
|
|
35
35
|
@Override
|
|
36
36
|
public boolean onLoadFailed(@androidx.annotation.Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
|
|
37
|
-
if (!events)
|
|
37
|
+
if (!events) {
|
|
38
|
+
if (target instanceof ImageViewTarget) {
|
|
39
|
+
((FastImageViewWithUrl) ((ImageViewTarget) target).getView()).onQuietLoadFailed();
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
38
43
|
FastImageOkHttpProgressGlideModule.forget(key);
|
|
39
44
|
if (!(target instanceof ImageViewTarget)) {
|
|
40
45
|
return false;
|
|
@@ -14,7 +14,12 @@ import androidx.annotation.Nullable;
|
|
|
14
14
|
|
|
15
15
|
import com.bumptech.glide.Glide;
|
|
16
16
|
import com.bumptech.glide.load.ImageHeaderParserUtils;
|
|
17
|
+
import com.bumptech.glide.load.MultiTransformation;
|
|
18
|
+
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
|
|
19
|
+
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
|
20
|
+
import com.bumptech.glide.load.resource.bitmap.CenterInside;
|
|
17
21
|
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
|
|
22
|
+
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
|
18
23
|
import com.bumptech.glide.load.resource.gif.GifDrawable;
|
|
19
24
|
import com.bumptech.glide.request.RequestOptions;
|
|
20
25
|
|
|
@@ -82,27 +87,37 @@ final class FastImageSourceSize {
|
|
|
82
87
|
|
|
83
88
|
// What RequestBuilder.into(ImageView) applies for the view's scale type
|
|
84
89
|
// (it leaves a transformation that's already set alone), with the
|
|
85
|
-
// downsample strategy it implies wrapped by capture
|
|
86
|
-
|
|
90
|
+
// downsample strategy it implies wrapped by capture, and then blur if it
|
|
91
|
+
// isn't null.
|
|
92
|
+
static RequestOptions scaleTypeOptions(@Nullable ImageView.ScaleType scaleType, Capture capture, @Nullable FastImageBlur blur) {
|
|
87
93
|
RequestOptions options = new RequestOptions();
|
|
94
|
+
BitmapTransformation transformation = null;
|
|
88
95
|
if (scaleType != null) {
|
|
89
96
|
switch (scaleType) {
|
|
90
97
|
case CENTER_CROP:
|
|
91
98
|
options = options.optionalCenterCrop();
|
|
99
|
+
transformation = new CenterCrop();
|
|
92
100
|
break;
|
|
93
101
|
case CENTER_INSIDE:
|
|
94
102
|
case FIT_XY:
|
|
95
103
|
options = options.optionalCenterInside();
|
|
104
|
+
transformation = new CenterInside();
|
|
96
105
|
break;
|
|
97
106
|
case FIT_CENTER:
|
|
98
107
|
case FIT_START:
|
|
99
108
|
case FIT_END:
|
|
100
109
|
options = options.optionalFitCenter();
|
|
110
|
+
transformation = new FitCenter();
|
|
101
111
|
break;
|
|
102
112
|
default:
|
|
103
113
|
break;
|
|
104
114
|
}
|
|
105
115
|
}
|
|
116
|
+
if (blur != null) {
|
|
117
|
+
options = transformation == null
|
|
118
|
+
? options.optionalTransform(blur)
|
|
119
|
+
: options.optionalTransform(new MultiTransformation<>(transformation, blur));
|
|
120
|
+
}
|
|
106
121
|
return options.downsample(capture);
|
|
107
122
|
}
|
|
108
123
|
|
|
@@ -22,6 +22,7 @@ import com.facebook.react.uimanager.LayoutShadowNode;
|
|
|
22
22
|
import com.facebook.react.uimanager.SimpleViewManager;
|
|
23
23
|
import com.facebook.react.bridge.ReactContext;
|
|
24
24
|
import com.facebook.react.uimanager.ThemedReactContext;
|
|
25
|
+
import com.facebook.react.uimanager.PixelUtil;
|
|
25
26
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
26
27
|
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
|
|
27
28
|
|
|
@@ -99,6 +100,26 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
|
|
|
99
100
|
view.setImageRendering(imageRendering);
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
@ReactProp(name = "blurRadius")
|
|
104
|
+
public void setBlurRadius(FastImageViewWithUrl view, float blurRadius) {
|
|
105
|
+
view.setBlurRadius(PixelUtil.toPixelFromDIP(blurRadius));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@ReactProp(name = "transitionDuration")
|
|
109
|
+
public void setTransitionDuration(FastImageViewWithUrl view, int transitionDuration) {
|
|
110
|
+
view.setTransitionDuration(transitionDuration);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@ReactProp(name = "transitionBetweenImages")
|
|
114
|
+
public void setTransitionBetweenImages(FastImageViewWithUrl view, boolean betweenImages) {
|
|
115
|
+
view.setTransitionBetweenImages(betweenImages);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@ReactProp(name = "transitionSkipOnCacheHit")
|
|
119
|
+
public void setTransitionSkipOnCacheHit(FastImageViewWithUrl view, @Nullable String skipOnCacheHit) {
|
|
120
|
+
view.setTransitionSkipOnCacheHit(skipOnCacheHit);
|
|
121
|
+
}
|
|
122
|
+
|
|
102
123
|
@ReactProp(name = "paused")
|
|
103
124
|
public void setPaused(FastImageViewWithUrl view, boolean paused) {
|
|
104
125
|
view.setPaused(paused);
|