Skip to content
This repository was archived by the owner on Apr 29, 2021. It is now read-only.

Commit ddd1ebb

Browse files
author
luoxuuguang
committed
add : add fadeInImage
1 parent fd0bd6d commit ddd1ebb

File tree

2 files changed

+381
-0
lines changed

2 files changed

+381
-0
lines changed

Runtime/widgets/fade_in_image.cs

Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
1+
using System;
2+
using Unity.UIWidgets.animation;
3+
using Unity.UIWidgets.foundation;
4+
using Unity.UIWidgets.painting;
5+
using Unity.UIWidgets.ui;
6+
using UnityEngine;
7+
using Color = Unity.UIWidgets.ui.Color;
8+
9+
namespace Unity.UIWidgets.widgets {
10+
public class FadeInImage : StatefulWidget {
11+
public FadeInImage(
12+
ImageProvider placeholder,
13+
ImageProvider image,
14+
TimeSpan? fadeOutDuration = null,
15+
Curve fadeOutCurve = null,
16+
TimeSpan? fadeInDuration = null,
17+
Curve fadeInCurve = null,
18+
float? width = null,
19+
float? height = null,
20+
BoxFit? fit = null,
21+
Alignment alignment = null,
22+
ImageRepeat repeat = ImageRepeat.noRepeat,
23+
bool matchTextDirection = false,
24+
Key key = null
25+
) : base(key) {
26+
D.assert(placeholder != null);
27+
D.assert(image != null);
28+
D.assert(fadeOutDuration != null);
29+
D.assert(fadeOutCurve != null);
30+
D.assert(fadeInDuration != null);
31+
D.assert(fadeInCurve != null);
32+
D.assert(alignment != null);
33+
this.placeholder = placeholder;
34+
this.image = image;
35+
this.width = width;
36+
this.height = height;
37+
this.fit = fit;
38+
this.fadeOutDuration = fadeOutDuration ?? TimeSpan.FromMilliseconds(300);
39+
this.fadeOutCurve = fadeOutCurve ?? Curves.easeOut;
40+
this.fadeInDuration = fadeInDuration ?? TimeSpan.FromMilliseconds(700);
41+
this.fadeInCurve = fadeInCurve ?? Curves.easeIn;
42+
this.alignment = alignment ?? Alignment.center;
43+
this.repeat = repeat;
44+
this.matchTextDirection = matchTextDirection;
45+
}
46+
47+
public static FadeInImage memoryNetwork(
48+
byte[] placeholder,
49+
string image,
50+
float placeholderScale = 1.0f,
51+
float imageScale = 1.0f,
52+
TimeSpan? fadeOutDuration = null,
53+
Curve fadeOutCurve = null,
54+
TimeSpan? fadeInDuration = null,
55+
Curve fadeInCurve = null,
56+
float? width = null,
57+
float? height = null,
58+
BoxFit? fit = null,
59+
Alignment alignment = null,
60+
ImageRepeat repeat = ImageRepeat.noRepeat,
61+
bool matchTextDirection = false,
62+
Key key = null
63+
) {
64+
D.assert(placeholder != null);
65+
D.assert(image != null);
66+
D.assert(fadeOutDuration != null);
67+
D.assert(fadeOutCurve != null);
68+
D.assert(fadeInDuration != null);
69+
D.assert(fadeInCurve != null);
70+
D.assert(alignment != null);
71+
var memoryImage = new MemoryImage(placeholder, placeholderScale);
72+
var networkImage = new NetworkImage(image, imageScale);
73+
return new FadeInImage(
74+
memoryImage,
75+
networkImage,
76+
fadeOutDuration,
77+
fadeOutCurve,
78+
fadeInDuration,
79+
fadeInCurve,
80+
width, height,
81+
fit,
82+
alignment,
83+
repeat,
84+
matchTextDirection
85+
);
86+
}
87+
88+
public static FadeInImage assetNetwork(
89+
string placeholder,
90+
string image,
91+
AssetBundle bundle = null,
92+
float placeholderScale = 0.0f,
93+
float imageScale = 1.0f,
94+
TimeSpan? fadeOutDuration = null,
95+
Curve fadeOutCurve = null,
96+
TimeSpan? fadeInDuration = null,
97+
Curve fadeInCurve = null,
98+
float? width = null,
99+
float? height = null,
100+
BoxFit? fit = null,
101+
Alignment alignment = null,
102+
ImageRepeat repeat = ImageRepeat.noRepeat,
103+
bool matchTextDirection = false,
104+
Key key = null
105+
) {
106+
D.assert(placeholder != null);
107+
D.assert(image != null);
108+
D.assert(fadeOutDuration != null);
109+
D.assert(fadeOutCurve != null);
110+
D.assert(fadeInDuration != null);
111+
D.assert(fadeInCurve != null);
112+
D.assert(alignment != null);
113+
var imageProvider = placeholderScale != null
114+
? new ExactAssetImage(placeholder, bundle: bundle, scale: placeholderScale)
115+
: (ImageProvider) new AssetImage(placeholder, bundle: bundle);
116+
117+
var networkImage = new NetworkImage(image, imageScale);
118+
return new FadeInImage(
119+
imageProvider,
120+
networkImage,
121+
fadeOutDuration,
122+
fadeOutCurve,
123+
fadeInDuration,
124+
fadeInCurve,
125+
width, height,
126+
fit,
127+
alignment,
128+
repeat,
129+
matchTextDirection
130+
);
131+
}
132+
133+
public readonly ImageProvider placeholder;
134+
public readonly ImageProvider image;
135+
public readonly TimeSpan fadeOutDuration;
136+
public readonly Curve fadeOutCurve;
137+
public readonly TimeSpan fadeInDuration;
138+
public readonly Curve fadeInCurve;
139+
public readonly float? width;
140+
public readonly float? height;
141+
public readonly BoxFit? fit;
142+
public readonly Alignment alignment;
143+
public readonly ImageRepeat repeat;
144+
public readonly bool matchTextDirection;
145+
146+
147+
public override State createState() {
148+
return new _FadeInImageState();
149+
}
150+
}
151+
152+
enum FadeInImagePhase {
153+
start,
154+
waiting,
155+
fadeOut,
156+
fadeIn,
157+
completed
158+
}
159+
160+
delegate void _ImageProviderResolverListener();
161+
162+
class _ImageProviderResolver {
163+
public _ImageProviderResolver(
164+
_FadeInImageState state,
165+
_ImageProviderResolverListener listener
166+
) {
167+
this.state = state;
168+
this.listener = listener;
169+
}
170+
171+
readonly _FadeInImageState state;
172+
readonly _ImageProviderResolverListener listener;
173+
174+
FadeInImage widget {
175+
get { return this.state.widget; }
176+
}
177+
178+
public ImageStream _imageStream;
179+
public ImageInfo _imageInfo;
180+
181+
public void resolve(ImageProvider provider) {
182+
ImageStream oldImageStream = this._imageStream;
183+
Size size = null;
184+
if (this.widget.width != null && this.widget.height != null) {
185+
size = new Size(Convert.ToSingle(this.widget.width), Convert.ToSingle(this.widget.height));
186+
}
187+
188+
this._imageStream = provider.resolve(ImageUtils.createLocalImageConfiguration(this.state.context, size));
189+
D.assert(this._imageStream != null);
190+
191+
if (this._imageStream.key != oldImageStream?.key) {
192+
oldImageStream?.removeListener(this._handleImageChanged);
193+
this._imageStream.addListener(this._handleImageChanged);
194+
}
195+
}
196+
197+
void _handleImageChanged(ImageInfo imageInfo, bool synchronousCall) {
198+
this._imageInfo = imageInfo;
199+
this.listener();
200+
}
201+
202+
public void stopListening() {
203+
this._imageStream?.removeListener(this._handleImageChanged);
204+
}
205+
}
206+
207+
208+
class _FadeInImageState : TickerProviderStateMixin<FadeInImage> {
209+
_ImageProviderResolver _imageResolver;
210+
_ImageProviderResolver _placeholderResolver;
211+
212+
AnimationController _controller;
213+
Animation<float> _animation;
214+
215+
FadeInImagePhase _phase = FadeInImagePhase.start;
216+
217+
public override void initState() {
218+
this._imageResolver = new _ImageProviderResolver(state: this, this._updatePhase);
219+
this._placeholderResolver = new _ImageProviderResolver(state: this, listener: () => {
220+
this.setState(() => {
221+
// Trigger rebuild to display the placeholder image
222+
});
223+
});
224+
this._controller = new AnimationController(
225+
value: 1.0f,
226+
vsync: this
227+
);
228+
this._controller.addListener(() => {
229+
this.setState(() => {
230+
// Trigger rebuild to update opacity value.
231+
});
232+
});
233+
this._controller.addStatusListener(status => { this._updatePhase(); });
234+
base.initState();
235+
}
236+
237+
public override void didChangeDependencies() {
238+
this._resolveImage();
239+
base.didChangeDependencies();
240+
}
241+
242+
public override void didUpdateWidget(StatefulWidget oldWidget) {
243+
base.didUpdateWidget(oldWidget);
244+
FadeInImage fadeInImage = oldWidget as FadeInImage;
245+
if (this.widget.image != fadeInImage.image || this.widget.placeholder != fadeInImage.placeholder) {
246+
this._resolveImage();
247+
}
248+
}
249+
250+
void _resolveImage() {
251+
this._imageResolver.resolve(this.widget.image);
252+
253+
if (this._isShowingPlaceholder) {
254+
this._placeholderResolver.resolve(this.widget.placeholder);
255+
}
256+
257+
if (this._phase == FadeInImagePhase.start) {
258+
this._updatePhase();
259+
}
260+
}
261+
262+
void _updatePhase() {
263+
this.setState(() => {
264+
switch (this._phase) {
265+
case FadeInImagePhase.start:
266+
if (this._imageResolver._imageInfo != null) {
267+
this._phase = FadeInImagePhase.completed;
268+
}
269+
else {
270+
this._phase = FadeInImagePhase.waiting;
271+
}
272+
273+
break;
274+
case FadeInImagePhase.waiting:
275+
if (this._imageResolver._imageInfo != null) {
276+
this._controller.duration = this.widget.fadeOutDuration;
277+
this._animation = new CurvedAnimation(
278+
parent: this._controller,
279+
curve: this.widget.fadeOutCurve
280+
);
281+
this._phase = FadeInImagePhase.fadeOut;
282+
this._controller.reverse(1.0f);
283+
}
284+
285+
break;
286+
case FadeInImagePhase.fadeOut:
287+
if (this._controller.status == AnimationStatus.dismissed) {
288+
// Done fading out placeholder. Begin target image fade-in.
289+
this._controller.duration = this.widget.fadeInDuration;
290+
this._animation = new CurvedAnimation(
291+
parent: this._controller,
292+
curve: this.widget.fadeInCurve
293+
);
294+
this._phase = FadeInImagePhase.fadeIn;
295+
this._placeholderResolver.stopListening();
296+
this._controller.forward(0.0f);
297+
}
298+
299+
break;
300+
case FadeInImagePhase.fadeIn:
301+
if (this._controller.status == AnimationStatus.completed) {
302+
// Done finding in new image.
303+
this._phase = FadeInImagePhase.completed;
304+
}
305+
306+
break;
307+
case FadeInImagePhase.completed:
308+
// Nothing to do.
309+
break;
310+
}
311+
});
312+
}
313+
314+
public override void dispose() {
315+
this._imageResolver.stopListening();
316+
this._placeholderResolver.stopListening();
317+
this._controller.dispose();
318+
base.dispose();
319+
}
320+
321+
bool _isShowingPlaceholder {
322+
get {
323+
switch (this._phase) {
324+
case FadeInImagePhase.start:
325+
case FadeInImagePhase.waiting:
326+
case FadeInImagePhase.fadeOut:
327+
return true;
328+
case FadeInImagePhase.fadeIn:
329+
case FadeInImagePhase.completed:
330+
return false;
331+
}
332+
333+
return true;
334+
}
335+
}
336+
337+
ImageInfo _imageInfo {
338+
get {
339+
return this._isShowingPlaceholder
340+
? this._placeholderResolver._imageInfo
341+
: this._imageResolver._imageInfo;
342+
}
343+
}
344+
345+
public override Widget build(BuildContext context) {
346+
D.assert(this._phase != FadeInImagePhase.start);
347+
ImageInfo imageInfo = this._imageInfo;
348+
return new RawImage(
349+
image: imageInfo?.image,
350+
width: this.widget.width,
351+
height: this.widget.height,
352+
scale: imageInfo?.scale ?? 1.0f,
353+
color: Color.fromRGBO(255, 255, 255, this._animation?.value ?? 1.0f),
354+
colorBlendMode: BlendMode.modulate,
355+
fit: this.widget.fit,
356+
alignment: this.widget.alignment,
357+
repeat: this.widget.repeat
358+
);
359+
}
360+
361+
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
362+
base.debugFillProperties(properties);
363+
properties.add(new EnumProperty<FadeInImagePhase>("phase", this._phase));
364+
properties.add(new DiagnosticsProperty<ImageInfo>("pixels", this._imageInfo));
365+
properties.add(new DiagnosticsProperty<ImageStream>("image stream", this._imageResolver._imageStream));
366+
properties.add(new DiagnosticsProperty<ImageStream>("placeholder stream",
367+
this._placeholderResolver._imageStream));
368+
}
369+
}
370+
}

Runtime/widgets/fade_in_image.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)