|
@@ -1,97 +1,174 @@
|
|
|
-// Copyright 2013 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.
|
|
|
-
|
|
|
import 'package:flutter/material.dart';
|
|
|
-import 'package:go_router/go_router.dart';
|
|
|
|
|
|
-/// This sample app shows an app with two screens.
|
|
|
-///
|
|
|
-/// The first route '/' is mapped to [HomeScreen], and the second route
|
|
|
-/// '/details' is mapped to [DetailsScreen].
|
|
|
-///
|
|
|
-/// The buttons use context.go() to navigate to each destination. On mobile
|
|
|
-/// devices, each destination is deep-linkable and on the web, can be navigated
|
|
|
-/// to using the address bar.
|
|
|
void main() => runApp(const MyApp());
|
|
|
|
|
|
-/// The route configuration.
|
|
|
-final GoRouter _router = GoRouter(
|
|
|
- routes: <RouteBase>[
|
|
|
- GoRoute(
|
|
|
- path: '/',
|
|
|
- builder: (BuildContext context, GoRouterState state) {
|
|
|
- return const HomeScreen();
|
|
|
- },
|
|
|
- routes: <RouteBase>[
|
|
|
- GoRoute(
|
|
|
- path: 'details',
|
|
|
- builder: (BuildContext context, GoRouterState state) {
|
|
|
- return const DetailsScreen();
|
|
|
- },
|
|
|
- ),
|
|
|
- ],
|
|
|
- ),
|
|
|
- ],
|
|
|
-);
|
|
|
-
|
|
|
-/// The main app.
|
|
|
class MyApp extends StatelessWidget {
|
|
|
- /// Constructs a [MyApp]
|
|
|
- const MyApp({Key? key}) : super(key: key);
|
|
|
+ const MyApp({super.key});
|
|
|
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
- return MaterialApp.router(
|
|
|
- routerConfig: _router,
|
|
|
+ Widget titleSection = Container(
|
|
|
+ padding: const EdgeInsets.all(32),
|
|
|
+ child: Row(
|
|
|
+ children: [
|
|
|
+ Expanded(
|
|
|
+ /*1*/
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ /*2*/
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.only(bottom: 8),
|
|
|
+ child: const Text(
|
|
|
+ 'Oeschinen Lake Campground',
|
|
|
+ style: TextStyle(
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Text(
|
|
|
+ 'Kandersteg, Switzerland',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.grey[500],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ const FavoriteWidget(),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
);
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
-/// The home screen
|
|
|
-class HomeScreen extends StatelessWidget {
|
|
|
- /// Constructs a [HomeScreen]
|
|
|
- const HomeScreen({Key? key}) : super(key: key);
|
|
|
+ Color color = Theme.of(context).primaryColor;
|
|
|
|
|
|
- @override
|
|
|
- Widget build(BuildContext context) {
|
|
|
- return Scaffold(
|
|
|
- appBar: AppBar(title: const Text('Home Screen')),
|
|
|
- body: Center(
|
|
|
- child: Column(
|
|
|
- mainAxisAlignment: MainAxisAlignment.center,
|
|
|
- children: <Widget>[
|
|
|
- ElevatedButton(
|
|
|
- onPressed: () => context.go('/details'),
|
|
|
- child: const Text('Go to the Details screen'),
|
|
|
+ Widget buttonSection = SizedBox(
|
|
|
+ child: Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
|
+ children: [
|
|
|
+ _buildButtonColumn(color, Icons.call, 'CALL'),
|
|
|
+ _buildButtonColumn(color, Icons.near_me, 'ROUTE'),
|
|
|
+ _buildButtonColumn(color, Icons.share, 'SHARE'),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+
|
|
|
+ Widget textSection = Container(
|
|
|
+ padding: const EdgeInsets.all(32),
|
|
|
+ child: const Text(
|
|
|
+ 'Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese '
|
|
|
+ 'Alps. Situated 1,578 meters above sea level, it is one of the '
|
|
|
+ 'larger Alpine Lakes. A gondola ride from Kandersteg, followed by a '
|
|
|
+ 'half-hour walk through pastures and pine forest, leads you to the '
|
|
|
+ 'lake, which warms to 20 degrees Celsius in the summer. Activities '
|
|
|
+ 'enjoyed here include rowing, and riding the summer toboggan run.',
|
|
|
+ softWrap: true,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+
|
|
|
+ return MaterialApp(
|
|
|
+ title: 'Flutter layout demo',
|
|
|
+ home: Scaffold(
|
|
|
+ appBar: AppBar(
|
|
|
+ title: const Text('Flutter layout demo'),
|
|
|
+ ),
|
|
|
+ body: ListView(
|
|
|
+ children: [
|
|
|
+ Image.asset(
|
|
|
+ 'images/lake.jpg',
|
|
|
+ width: 600,
|
|
|
+ height: 240,
|
|
|
+ fit: BoxFit.cover,
|
|
|
),
|
|
|
+ titleSection,
|
|
|
+ buttonSection,
|
|
|
+ textSection,
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
+
|
|
|
+ Column _buildButtonColumn(Color color, IconData icon, String label) {
|
|
|
+ return Column(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ mainAxisAlignment: MainAxisAlignment.center,
|
|
|
+ children: [
|
|
|
+ Icon(icon, color: color),
|
|
|
+ Container(
|
|
|
+ margin: const EdgeInsets.only(top: 8),
|
|
|
+ child: Text(
|
|
|
+ label,
|
|
|
+ style: TextStyle(
|
|
|
+ fontSize: 12,
|
|
|
+ fontWeight: FontWeight.w400,
|
|
|
+ color: color,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-/// The details screen
|
|
|
-class DetailsScreen extends StatelessWidget {
|
|
|
- /// Constructs a [DetailsScreen]
|
|
|
- const DetailsScreen({Key? key}) : super(key: key);
|
|
|
+// #docregion FavoriteWidget
|
|
|
+class FavoriteWidget extends StatefulWidget {
|
|
|
+ const FavoriteWidget({super.key});
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<FavoriteWidget> createState() => _FavoriteWidgetState();
|
|
|
+}
|
|
|
+// #enddocregion FavoriteWidget
|
|
|
+
|
|
|
+// #docregion _FavoriteWidgetState, _FavoriteWidgetState-fields, _FavoriteWidgetState-build
|
|
|
+class _FavoriteWidgetState extends State<FavoriteWidget> {
|
|
|
+ // #enddocregion _FavoriteWidgetState-build
|
|
|
+ bool _isFavorited = true;
|
|
|
+ int _favoriteCount = 41;
|
|
|
+
|
|
|
+ // #enddocregion _FavoriteWidgetState-fields
|
|
|
|
|
|
+ // #docregion _toggleFavorite
|
|
|
+ void _toggleFavorite() {
|
|
|
+ setState(() {
|
|
|
+ if (_isFavorited) {
|
|
|
+ _favoriteCount -= 1;
|
|
|
+ _isFavorited = false;
|
|
|
+ } else {
|
|
|
+ _favoriteCount += 1;
|
|
|
+ _isFavorited = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // #enddocregion _toggleFavorite
|
|
|
+
|
|
|
+ // #docregion _FavoriteWidgetState-build
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
- return Scaffold(
|
|
|
- appBar: AppBar(title: const Text('Details Screen')),
|
|
|
- body: Center(
|
|
|
- child: Column(
|
|
|
- mainAxisAlignment: MainAxisAlignment.center,
|
|
|
- children: <ElevatedButton>[
|
|
|
- ElevatedButton(
|
|
|
- onPressed: () => context.go('/'),
|
|
|
- child: const Text('Go back to the Home screen'),
|
|
|
- ),
|
|
|
- ],
|
|
|
+ return Row(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.all(0),
|
|
|
+ child: IconButton(
|
|
|
+ padding: const EdgeInsets.all(0),
|
|
|
+ alignment: Alignment.centerRight,
|
|
|
+ icon: (_isFavorited
|
|
|
+ ? const Icon(Icons.star)
|
|
|
+ : const Icon(Icons.star_border)),
|
|
|
+ color: Colors.red[500],
|
|
|
+ onPressed: _toggleFavorite,
|
|
|
+ ),
|
|
|
),
|
|
|
- ),
|
|
|
+ SizedBox(
|
|
|
+ width: 18,
|
|
|
+ child: SizedBox(
|
|
|
+ child: Text('$_favoriteCount'),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
);
|
|
|
}
|
|
|
-}
|
|
|
+// #docregion _FavoriteWidgetState-fields
|
|
|
+}
|