Skip to content

Commit

Permalink
Fix crash on network fail #275 (#308)
Browse files Browse the repository at this point in the history
When retrieving images from the network, things can go south.
This fixes a bug when the network goes down, photo_view would crash when retrieving remote images.

Fixes: #275
  • Loading branch information
renancaraujo authored Aug 11, 2020
1 parent a5ad0d0 commit c9d5885
Show file tree
Hide file tree
Showing 18 changed files with 702 additions and 677 deletions.
Binary file added example/assets/neat.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed example/assets/peanut.gif
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,38 @@ class ExampleAppBar extends StatelessWidget {
)));
}
}

class ExampleAppBarLayout extends StatelessWidget {
const ExampleAppBarLayout({
Key key,
@required this.title,
this.showGoBack,
this.child,
}) : super(key: key);

final String title;
final bool showGoBack;
final Widget child;

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromARGB(255, 255, 255, 255),
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ExampleAppBar(
title: title,
showGoBack: showGoBack,
),
Expanded(
child: child,
),
],
),
),
);
}
}
45 changes: 45 additions & 0 deletions example/lib/screens/common/common_example_wrapper.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';

class CommonExampleRouteWrapper extends StatelessWidget {
const CommonExampleRouteWrapper({
this.imageProvider,
this.loadingBuilder,
this.backgroundDecoration,
this.minScale,
this.maxScale,
this.initialScale,
this.basePosition = Alignment.center,
this.filterQuality = FilterQuality.none,
});

final ImageProvider imageProvider;
final LoadingBuilder loadingBuilder;
final Decoration backgroundDecoration;
final dynamic minScale;
final dynamic maxScale;
final dynamic initialScale;
final Alignment basePosition;
final FilterQuality filterQuality;

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
constraints: BoxConstraints.expand(
height: MediaQuery.of(context).size.height,
),
child: PhotoView(
imageProvider: imageProvider,
loadingBuilder: loadingBuilder,
backgroundDecoration: backgroundDecoration,
minScale: minScale,
maxScale: maxScale,
initialScale: initialScale,
basePosition: basePosition,
filterQuality: filterQuality,
),
),
);
}
}
43 changes: 43 additions & 0 deletions example/lib/screens/common/example_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';

class ExampleButtonNode extends StatelessWidget {
const ExampleButtonNode({
this.title,
this.onPressed,
});

final String title;
final Function onPressed;

@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(
vertical: 20.0,
),
child: Column(
children: <Widget>[
Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.black,
fontSize: 21.0,
fontWeight: FontWeight.w600,
),
),
Container(
margin: const EdgeInsets.only(
top: 10.0,
),
child: RaisedButton(
onPressed: onPressed,
child: const Text("Open example"),
color: Colors.amber,
),
)
],
),
);
}
}
165 changes: 165 additions & 0 deletions example/lib/screens/examples/common_use_cases_examples.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view_example/screens/common/app_bar.dart';
import 'package:photo_view_example/screens/common/common_example_wrapper.dart';
import 'package:photo_view_example/screens/common/example_button.dart';

class CommonUseCasesExamples extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ExampleAppBarLayout(
title: "Common use cases",
showGoBack: true,
child: ListView(
children: <Widget>[
ExampleButtonNode(
title: "Large Image",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/large-image.jpg"),
),
),
);
},
),
ExampleButtonNode(
title: "Large Image (filter quality: medium)",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/large-image.jpg"),
filterQuality: FilterQuality.medium,
),
),
);
},
),
ExampleButtonNode(
title: "Small Image (custom background)",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/small-image.jpg"),
backgroundDecoration: BoxDecoration(
gradient: LinearGradient(
colors: <Color>[Colors.white, Colors.grey],
stops: [0.1, 1.0],
),
),
),
),
);
},
),
ExampleButtonNode(
title: "Small Image (custom alignment)",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/small-image.jpg"),
backgroundDecoration: BoxDecoration(
color: Colors.white,
),
basePosition: Alignment(0.5, 0.0),
),
),
);
},
),
ExampleButtonNode(
title: "Animated GIF",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/neat.gif"),
),
),
);
},
),
ExampleButtonNode(
title: "Limited scale",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/large-image.jpg"),
minScale: PhotoViewComputedScale.contained * 0.8,
maxScale: PhotoViewComputedScale.covered * 1.1,
initialScale: PhotoViewComputedScale.covered * 1.1,
),
),
);
},
),
ExampleButtonNode(
title: "Custom Initial scale",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CommonExampleRouteWrapper(
imageProvider: const AssetImage("assets/large-image.jpg"),
initialScale: PhotoViewComputedScale.contained * 0.7,
),
),
);
},
),
ExampleButtonNode(
title: "One tap to dismiss",
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const OneTapWrapper(
imageProvider: const AssetImage("assets/large-image.jpg"),
),
),
);
},
),
],
),
);
}
}

class OneTapWrapper extends StatelessWidget {
const OneTapWrapper({
this.imageProvider,
});

final ImageProvider imageProvider;

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
constraints: BoxConstraints.expand(
height: MediaQuery.of(context).size.height,
),
child: GestureDetector(
onTapDown: (_) {
Navigator.pop(context);
},
child: PhotoView(
imageProvider: imageProvider,
),
),
),
);
}
}
70 changes: 28 additions & 42 deletions example/lib/screens/examples/controller_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'dart:math';

import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view_example/screens/app_bar.dart';
import 'package:photo_view_example/screens/common/app_bar.dart';

class ControllerExample extends StatefulWidget {
@override
Expand Down Expand Up @@ -52,51 +52,37 @@ class _ControllerExampleState extends State<ControllerExample> {

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
return ExampleAppBarLayout(
title: "Controller",
showGoBack: true,
child: ClipRect(
child: Stack(
children: <Widget>[
const ExampleAppBar(
title: "Controller Examples",
showGoBack: true,
Positioned.fill(
child: PhotoView(
imageProvider: const AssetImage("assets/large-image.jpg"),
controller: controller,
scaleStateController: scaleStateController,
enableRotation: true,
initialScale: minScale,
minScale: minScale,
maxScale: maxScale,
),
),
Flexible(
flex: 1,
child: ClipRect(
child: Stack(
children: <Widget>[
Positioned.fill(
child: PhotoView(
imageProvider:
const AssetImage("assets/large-image.jpg"),
controller: controller,
scaleStateController: scaleStateController,
enableRotation: true,
initialScale: minScale,
minScale: minScale,
maxScale: maxScale,
),
),
Positioned(
bottom: 0,
height: 290,
left: 0,
right: 0,
child: Container(
padding: const EdgeInsets.all(30.0),
child: StreamBuilder(
stream: controller.outputStateStream,
initialData: controller.value,
builder: _streamBuild,
),
),
)
],
Positioned(
bottom: 0,
height: 290,
left: 0,
right: 0,
child: Container(
padding: const EdgeInsets.all(30.0),
child: StreamBuilder(
stream: controller.outputStateStream,
initialData: controller.value,
builder: _streamBuild,
),
),
),
)
],
),
),
Expand Down
Loading

0 comments on commit c9d5885

Please sign in to comment.