flutter/examples/api/lib/material/navigation_rail/navigation_rail.extended_animation.0.dart
Greg Spencer ab2b0851a2
Add smoke tests for all the examples, fix 17 broken examples. (#89021)
This adds a smoke test for every single API example. It also fixes 17 tests that had bugs in them, or were otherwise broken, and even fixes one actual bug in the framework, and one limitation in the framework.

The bug in the framework is that NetworkImage's _loadAsync method had await response.drain<List<int>>();, but if the response is null, it will throw a cryptic exception saying that Null can't be assigned to List<int>. The fix was just to use await response.drain<void>(); instead.

The limitation is that RelativePositionedTransition takes an Animation<Rect> rect parameter, and if you want to use a RectTween with it, the value emitted there is Rect?, and one of the examples was just casting from Animation<Rect> to Animation<Rect?>, which is invalid, so I modified RelativePositionedTransition to take a Rect? and just use Rect.zero if the rect is null.
2021-09-28 09:32:06 -07:00

170 lines
6.1 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Template: dev/snippets/config/templates/freeform.tmpl
//
// Comment lines marked with "▼▼▼" and "▲▲▲" are used for authoring
// of samples, and may be ignored if you are just exploring the sample.
// Flutter code sample for NavigationRail.extendedAnimation
//
//***************************************************************************
//* ▼▼▼▼▼▼▼▼ description ▼▼▼▼▼▼▼▼ (do not modify or remove section marker)
// This example shows how to use this animation to create a [FloatingActionButton]
// that animates itself between the normal and extended states of the
// [NavigationRail].
//
// An instance of `MyNavigationRailFab` is created for [NavigationRail.leading].
// Pressing the FAB button toggles the "extended" state of the [NavigationRail].
//* ▲▲▲▲▲▲▲▲ description ▲▲▲▲▲▲▲▲ (do not modify or remove section marker)
//***************************************************************************
//********************************************************************************
//* ▼▼▼▼▼▼▼▼ code-dartImports ▼▼▼▼▼▼▼▼ (do not modify or remove section marker)
import 'dart:ui';
//* ▲▲▲▲▲▲▲▲ code-dartImports ▲▲▲▲▲▲▲▲ (do not modify or remove section marker)
//********************************************************************************
import 'package:flutter/material.dart';
//********************************************************************************
//* ▼▼▼▼▼▼▼▼ code-main ▼▼▼▼▼▼▼▼ (do not modify or remove section marker)
void main() => runApp(const MyApp());
//* ▲▲▲▲▲▲▲▲ code-main ▲▲▲▲▲▲▲▲ (do not modify or remove section marker)
//********************************************************************************
//********************************************************************************
//* ▼▼▼▼▼▼▼▼ code-preamble ▼▼▼▼▼▼▼▼ (do not modify or remove section marker)
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'NavigationRail.extendedAnimation Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyNavigationRail(),
),
);
}
}
class MyNavigationRail extends StatefulWidget {
const MyNavigationRail({Key? key}) : super(key: key);
@override
State<MyNavigationRail> createState() => _MyNavigationRailState();
}
class _MyNavigationRailState extends State<MyNavigationRail> {
int _selectedIndex = 0;
bool _extended = false;
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
extended: _extended,
leading: MyNavigationRailFab(onPressed: () {
setState(() {
_extended = !_extended;
});
}),
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.none,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: Center(
child: Text('selectedIndex: $_selectedIndex'),
),
)
],
);
}
}
//* ▲▲▲▲▲▲▲▲ code-preamble ▲▲▲▲▲▲▲▲ (do not modify or remove section marker)
//********************************************************************************
//********************************************************************
//* ▼▼▼▼▼▼▼▼ code ▼▼▼▼▼▼▼▼ (do not modify or remove section marker)
class MyNavigationRailFab extends StatelessWidget {
const MyNavigationRailFab({Key? key, this.onPressed}) : super(key: key);
final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
final Animation<double> animation = NavigationRail.extendedAnimation(context);
return AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget? child) {
// The extended fab has a shorter height than the regular fab.
return Container(
height: 56,
padding: EdgeInsets.symmetric(
vertical: lerpDouble(0, 6, animation.value)!,
),
child: animation.value == 0
? FloatingActionButton(
child: const Icon(Icons.add),
onPressed: onPressed,
)
: Align(
alignment: AlignmentDirectional.centerStart,
widthFactor: animation.value,
child: Padding(
padding: const EdgeInsetsDirectional.only(start: 8),
child: FloatingActionButton.extended(
icon: const Icon(Icons.add),
label: const Text('CREATE'),
onPressed: onPressed,
),
),
),
);
},
);
}
}
//* ▲▲▲▲▲▲▲▲ code ▲▲▲▲▲▲▲▲ (do not modify or remove section marker)
//********************************************************************