Added pull to refresh
This commit is contained in:
parent
be48e955c7
commit
a955ecbfc0
7 changed files with 259 additions and 141 deletions
|
@ -1,3 +1,6 @@
|
|||
v2.3.0
|
||||
Added pull to refresh
|
||||
|
||||
v2.2.0
|
||||
Added refresh button on error
|
||||
|
||||
|
|
38
lib/components/sliver_persistent_header_padding.dart
Normal file
38
lib/components/sliver_persistent_header_padding.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class SliverPersistentHeaderPadding extends StatelessWidget {
|
||||
final double maxHeight;
|
||||
|
||||
const SliverPersistentHeaderPadding({required this.maxHeight});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SliverPersistentHeader(
|
||||
delegate: _SliverPersistentHeaderPaddingDelegate(maxHeight: maxHeight,),
|
||||
floating: false,
|
||||
pinned: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SliverPersistentHeaderPaddingDelegate extends SliverPersistentHeaderDelegate {
|
||||
final double maxHeight;
|
||||
|
||||
const _SliverPersistentHeaderPaddingDelegate({required this.maxHeight});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
@override
|
||||
double get maxExtent => maxHeight;
|
||||
|
||||
@override
|
||||
double get minExtent => 0;
|
||||
|
||||
@override
|
||||
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
|
||||
return oldDelegate.maxExtent != maxExtent;
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ class TrainInfo extends StatelessWidget {
|
|||
return TrainInfoErrorMaterial(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
|
||||
}
|
||||
|
||||
return TrainInfoMaterial(trainData: snapshot.data!,);
|
||||
return TrainInfoMaterial(trainData: snapshot.data!, refresh: refresh,);
|
||||
case UiDesign.CUPERTINO:
|
||||
if ([RefreshFutureBuilderState.none, RefreshFutureBuilderState.waiting].contains(snapshot.state)) {
|
||||
return TrainInfoLoadingCupertino(title: trainNumber.toString(),);
|
||||
|
@ -45,7 +45,7 @@ class TrainInfo extends StatelessWidget {
|
|||
return TrainInfoErrorCupertino(title: '$trainNumber - Error', error: snapshot.error!, refresh: refresh,);
|
||||
}
|
||||
|
||||
return TrainInfoCupertino(trainData: snapshot.data!,);
|
||||
return TrainInfoCupertino(trainData: snapshot.data!, refresh: refresh,);
|
||||
default:
|
||||
throw UnmatchedUiDesignException(uiDesign);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:info_tren/components/cupertino_divider.dart';
|
||||
import 'package:info_tren/components/sliver_persistent_header_padding.dart';
|
||||
import 'package:info_tren/models/train_data.dart' hide State;
|
||||
import 'package:info_tren/models/ui_design.dart';
|
||||
import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
|
||||
|
@ -58,8 +61,9 @@ class TrainInfoErrorCupertino extends TrainInfoError {
|
|||
|
||||
class TrainInfoCupertino extends StatelessWidget {
|
||||
final TrainData trainData;
|
||||
final Future Function()? refresh;
|
||||
|
||||
TrainInfoCupertino({required this.trainData});
|
||||
TrainInfoCupertino({required this.trainData, this.refresh,});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -74,84 +78,153 @@ class TrainInfoCupertino extends StatelessWidget {
|
|||
builder: (context) {
|
||||
final topPadding = MediaQuery.of(context).padding.top;
|
||||
|
||||
return CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: topPadding,
|
||||
),
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
DisplayTrainID(trainData: trainData,),
|
||||
DisplayTrainOperator(trainData: trainData,),
|
||||
DisplayTrainRoute(trainData: trainData,),
|
||||
DisplayTrainDeparture(trainData: trainData,),
|
||||
SliverToBoxAdapter(
|
||||
child: CupertinoDivider(
|
||||
color: FOREGROUND_WHITE,
|
||||
),
|
||||
),
|
||||
DisplayTrainLastInfo(trainData: trainData,),
|
||||
SliverToBoxAdapter(
|
||||
child: CupertinoDivider(),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
// Expanded(
|
||||
// child: DisplayTrainNextStop(trainData: trainData,),
|
||||
// ),
|
||||
Expanded(
|
||||
child: DisplayTrainDestination(trainData: trainData,),
|
||||
return NestedScrollView(
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) {
|
||||
return [
|
||||
// SliverPadding(
|
||||
// padding: EdgeInsets.only(
|
||||
// top: topPadding,
|
||||
// ),
|
||||
// ),
|
||||
SliverPersistentHeaderPadding(maxHeight: topPadding,)
|
||||
];
|
||||
},
|
||||
body: Builder(
|
||||
builder: (context) {
|
||||
return CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
if (refresh != null)
|
||||
CupertinoSliverRefreshControl(
|
||||
builder: (context, mode, pulledExtent, refreshTriggerPullDistance, refreshIndicatorExtent) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
height: pulledExtent,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: min(refreshIndicatorExtent, pulledExtent),
|
||||
child: Center(
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
if (mode == RefreshIndicatorMode.inactive) {
|
||||
return Container();
|
||||
}
|
||||
else if (mode == RefreshIndicatorMode.done) {
|
||||
return Text('Refreshed!');
|
||||
}
|
||||
else if (mode == RefreshIndicatorMode.drag) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CupertinoActivityIndicator(animating: false,),
|
||||
Text('Pull to refresh...'),
|
||||
],
|
||||
);
|
||||
}
|
||||
else if (mode == RefreshIndicatorMode.armed) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CupertinoActivityIndicator(animating: false,),
|
||||
Text('Release to refresh...'),
|
||||
],
|
||||
);
|
||||
}
|
||||
else {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CupertinoActivityIndicator(),
|
||||
Text('Refreshing'),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(child: Container(),),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
onRefresh: refresh,
|
||||
),
|
||||
SizedBox(
|
||||
height: double.infinity,
|
||||
child: CupertinoVerticalDivider(),
|
||||
DisplayTrainID(trainData: trainData,),
|
||||
DisplayTrainOperator(trainData: trainData,),
|
||||
DisplayTrainRoute(trainData: trainData,),
|
||||
DisplayTrainDeparture(trainData: trainData,),
|
||||
SliverToBoxAdapter(
|
||||
child: CupertinoDivider(
|
||||
color: FOREGROUND_WHITE,
|
||||
),
|
||||
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: CupertinoDivider(),
|
||||
// ),
|
||||
// SliverToBoxAdapter(
|
||||
// child: IntrinsicHeight(
|
||||
// child: Row(
|
||||
// children: <Widget>[
|
||||
// // Expanded(
|
||||
// // child: DisplayTrainRouteDuration(trainData: trainData,),
|
||||
// // ),
|
||||
// Expanded(child: Container(),),
|
||||
// SizedBox(
|
||||
// height: double.infinity,
|
||||
// child: CupertinoVerticalDivider(),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: DisplayTrainRouteDistance(trainData: trainData,),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
SliverToBoxAdapter(
|
||||
child: CupertinoDivider(
|
||||
color: FOREGROUND_WHITE,
|
||||
),
|
||||
),
|
||||
DisplayTrainStations(
|
||||
trainData: trainData,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).viewPadding.bottom,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
DisplayTrainLastInfo(trainData: trainData,),
|
||||
SliverToBoxAdapter(
|
||||
child: CupertinoDivider(),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
// Expanded(
|
||||
// child: DisplayTrainNextStop(trainData: trainData,),
|
||||
// ),
|
||||
Expanded(
|
||||
child: DisplayTrainDestination(trainData: trainData,),
|
||||
),
|
||||
SizedBox(
|
||||
height: double.infinity,
|
||||
child: CupertinoVerticalDivider(),
|
||||
),
|
||||
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: CupertinoDivider(),
|
||||
// ),
|
||||
// SliverToBoxAdapter(
|
||||
// child: IntrinsicHeight(
|
||||
// child: Row(
|
||||
// children: <Widget>[
|
||||
// // Expanded(
|
||||
// // child: DisplayTrainRouteDuration(trainData: trainData,),
|
||||
// // ),
|
||||
// Expanded(child: Container(),),
|
||||
// SizedBox(
|
||||
// height: double.infinity,
|
||||
// child: CupertinoVerticalDivider(),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: DisplayTrainRouteDistance(trainData: trainData,),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
SliverToBoxAdapter(
|
||||
child: CupertinoDivider(
|
||||
color: FOREGROUND_WHITE,
|
||||
),
|
||||
),
|
||||
DisplayTrainStations(
|
||||
trainData: trainData,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).viewPadding.bottom,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
|
|
|
@ -264,7 +264,7 @@ class ArrivalTime extends StatelessWidget {
|
|||
|
||||
final now = DateTime.now();
|
||||
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
|
||||
final newDate = oldDate.subtract(Duration(minutes: delay));
|
||||
final newDate = oldDate.add(Duration(minutes: delay));
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
@ -398,7 +398,7 @@ class DepartureTime extends StatelessWidget {
|
|||
|
||||
final now = DateTime.now();
|
||||
final oldDate = DateTime(now.year, now.month, now.day, splits[0], splits[1]);
|
||||
final newDate = oldDate.subtract(Duration(minutes: delay));
|
||||
final newDate = oldDate.add(Duration(minutes: delay));
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
|
|
@ -59,8 +59,9 @@ bool isSmallScreen(BuildContext context) => MediaQuery.of(context).size.height <
|
|||
|
||||
class TrainInfoMaterial extends StatelessWidget {
|
||||
final TrainData trainData;
|
||||
final Future Function()? refresh;
|
||||
|
||||
TrainInfoMaterial({required this.trainData});
|
||||
TrainInfoMaterial({required this.trainData, this.refresh,});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -80,69 +81,72 @@ class TrainInfoMaterial extends StatelessWidget {
|
|||
Expanded(
|
||||
child: SafeArea(
|
||||
bottom: false,
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainID(trainData: trainData,),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainOperator(trainData: trainData,),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(left: 2, right: 2),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: DisplayTrainRoute(trainData: trainData,),
|
||||
child: RefreshIndicator(
|
||||
onRefresh: refresh ?? () async {},
|
||||
child: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainID(trainData: trainData,),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainDeparture(trainData: trainData,),
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: Divider(
|
||||
// color: Colors.white70,
|
||||
// height: isSmallScreen(context) ? 8 : 16,
|
||||
// ),
|
||||
// ),
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainLastInfo(trainData: trainData,),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
|
||||
Expanded(child: DisplayTrainDestination(trainData: trainData,)),
|
||||
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
|
||||
],
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainOperator(trainData: trainData,),
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.only(left: 2, right: 2),
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: DisplayTrainRoute(trainData: trainData,),
|
||||
),
|
||||
),
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: IntrinsicHeight(
|
||||
// child: Row(
|
||||
// children: <Widget>[
|
||||
// // Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
|
||||
// Expanded(child: Container(),),
|
||||
// Expanded(child: DisplayTrainRouteDistance(trainData: trainData,)),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
color: Colors.white70,
|
||||
height: isSmallScreen(context) ? 8 : 16,
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainDeparture(trainData: trainData,),
|
||||
),
|
||||
),
|
||||
DisplayTrainStations(
|
||||
trainData: trainData,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).viewPadding.bottom,
|
||||
// SliverToBoxAdapter(
|
||||
// child: Divider(
|
||||
// color: Colors.white70,
|
||||
// height: isSmallScreen(context) ? 8 : 16,
|
||||
// ),
|
||||
// ),
|
||||
SliverToBoxAdapter(
|
||||
child: DisplayTrainLastInfo(trainData: trainData,),
|
||||
),
|
||||
),
|
||||
],
|
||||
SliverToBoxAdapter(
|
||||
child: IntrinsicHeight(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
|
||||
Expanded(child: DisplayTrainDestination(trainData: trainData,)),
|
||||
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: IntrinsicHeight(
|
||||
// child: Row(
|
||||
// children: <Widget>[
|
||||
// // Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
|
||||
// Expanded(child: Container(),),
|
||||
// Expanded(child: DisplayTrainRouteDistance(trainData: trainData,)),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
color: Colors.white70,
|
||||
height: isSmallScreen(context) ? 8 : 16,
|
||||
),
|
||||
),
|
||||
DisplayTrainStations(
|
||||
trainData: trainData,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Container(
|
||||
height: MediaQuery.of(context).viewPadding.bottom,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -11,7 +11,7 @@ description: O aplicație de vizualizare a datelor puse la dispoziție de Inform
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 2.2.0
|
||||
version: 2.3.0
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
|
Loading…
Add table
Reference in a new issue