Created
October 5, 2022 01:49
-
-
Save HansMuller/02ff5de511daa60688e0d288162ea471 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| class Star { | |
| const Star({ | |
| this.fillColor = Colors.white, | |
| this.borderColor = Colors.black, | |
| this.borderWidth = 9, | |
| this.points = 7, | |
| this.innerRadiusRatio = 0.75, | |
| this.pointRounding = 0.5, | |
| this.valleyRounding = 0.25, | |
| this.title = '<no title>', | |
| this.titleColor = Colors.black, | |
| }); | |
| final Color fillColor; | |
| final Color borderColor; | |
| final double borderWidth; | |
| final double points; | |
| final double innerRadiusRatio; | |
| final double pointRounding; | |
| final double valleyRounding; | |
| final String title; | |
| final Color titleColor; | |
| Star copyWith({ | |
| Color? fillColor, | |
| Color? borderColor, | |
| double? borderWidth, | |
| double? points, | |
| double? innerRadiusRatio, | |
| double? pointRounding, | |
| double? valleyRounding, | |
| String? title, | |
| Color? titleColor, | |
| }) { | |
| return Star( | |
| fillColor: fillColor ?? this.fillColor, | |
| borderColor: borderColor ?? this.borderColor, | |
| borderWidth: borderWidth ?? this.borderWidth, | |
| points: points ?? this.points, | |
| innerRadiusRatio: innerRadiusRatio ?? this.innerRadiusRatio, | |
| pointRounding: pointRounding ?? this.pointRounding, | |
| valleyRounding: valleyRounding ?? this.valleyRounding, | |
| title: title ?? this.title, | |
| titleColor: titleColor ?? this.titleColor, | |
| ); | |
| } | |
| } | |
| class StarView extends StatefulWidget { | |
| const StarView({ super.key, required this.star, required this.onStarChanged }); | |
| final Star star; | |
| final ValueChanged<Star> onStarChanged; | |
| @override | |
| State<StarView> createState() => _StarViewState(); | |
| } | |
| class _StarViewState extends State<StarView> { | |
| late final TextEditingController textController; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Container( | |
| padding: const EdgeInsets.all(32), | |
| alignment: Alignment.center, | |
| child: TextButton( | |
| style: TextButton.styleFrom( | |
| backgroundColor: widget.star.fillColor, | |
| foregroundColor: widget.star.titleColor, | |
| minimumSize: const Size.square(double.infinity), | |
| shape: StarBorder( | |
| side: BorderSide( | |
| color: widget.star.borderColor, | |
| width: widget.star.borderWidth, | |
| ), | |
| points: widget.star.points, | |
| innerRadiusRatio: widget.star.innerRadiusRatio, | |
| pointRounding: widget.star.pointRounding, | |
| valleyRounding: widget.star.valleyRounding, | |
| ), | |
| ), | |
| onPressed: () { | |
| widget.onStarChanged( | |
| widget.star.copyWith( | |
| borderWidth: (widget.star.borderWidth * 1.05).clamp(1, 20), | |
| innerRadiusRatio: (widget.star.innerRadiusRatio * .925).clamp(0.25, 0.75), | |
| ), | |
| ); | |
| }, | |
| child: Text(widget.star.title), | |
| ), | |
| ); | |
| } | |
| } | |
| class StarHome extends StatefulWidget { | |
| const StarHome({ super.key, required this.toggleDarkMode }); | |
| final VoidCallback toggleDarkMode; | |
| @override | |
| State<StarHome> createState() => _StarHomeState(); | |
| } | |
| class _StarHomeState extends State<StarHome> { | |
| int selectedIndex = 0; | |
| late List<Star> stars; | |
| // Runs when the Theme changes, which resets all of the stars' properties. | |
| // Seems like a feature for this demo. | |
| @override | |
| void didChangeDependencies() { | |
| super.didChangeDependencies(); | |
| final ColorScheme colorScheme = Theme.of(context).colorScheme; | |
| stars = <Star>[ | |
| Star( | |
| title: 'One', | |
| titleColor: colorScheme.onPrimaryContainer, | |
| fillColor: colorScheme.primaryContainer, | |
| borderColor: colorScheme.primary, | |
| ), | |
| Star( | |
| title: 'Two', | |
| titleColor: colorScheme.onPrimaryContainer, | |
| fillColor: colorScheme.primaryContainer, | |
| borderColor: colorScheme.primary, | |
| points: 5, | |
| borderWidth: 13, | |
| innerRadiusRatio: 0.5 | |
| ), | |
| Star( | |
| title: 'Free', | |
| titleColor: colorScheme.onPrimaryContainer, | |
| fillColor: colorScheme.tertiaryContainer, | |
| borderColor: colorScheme.tertiary, | |
| points: 13, | |
| borderWidth: 7, | |
| ), | |
| Star( | |
| title: 'Four', | |
| titleColor: colorScheme.onErrorContainer, | |
| fillColor: colorScheme.errorContainer, | |
| borderColor: colorScheme.error, | |
| points: 3, | |
| borderWidth: 15, | |
| innerRadiusRatio: 0.35, | |
| ), | |
| ]; | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| final ColorScheme colorScheme = Theme.of(context).colorScheme; | |
| final double appWidth = MediaQuery.of(context).size.width; | |
| final Widget floatingActionButton = FloatingActionButton( | |
| onPressed: widget.toggleDarkMode, | |
| child: const Icon(Icons.wb_sunny_outlined), | |
| ); | |
| final Widget view = Container( | |
| padding: const EdgeInsets.all(64), | |
| alignment: Alignment.center, | |
| color: colorScheme.background, | |
| child: AspectRatio( | |
| aspectRatio: 1, | |
| child: StarView( | |
| key: ValueKey<int>(selectedIndex), | |
| star: stars[selectedIndex], | |
| onStarChanged: (Star newStar) { | |
| setState(() { | |
| stars[selectedIndex] = newStar; | |
| }); | |
| }, | |
| ), | |
| ), | |
| ); | |
| if (appWidth > 440) { | |
| final Widget navigationRail = NavigationRail( | |
| selectedIndex: selectedIndex, | |
| groupAlignment: -0.75, | |
| labelType: appWidth < 800 ? NavigationRailLabelType.all : null, | |
| extended: appWidth >= 800, | |
| minExtendedWidth: 148, | |
| onDestinationSelected: (int index) { | |
| setState(() { | |
| selectedIndex = index; | |
| }); | |
| }, | |
| leading: floatingActionButton, | |
| destinations: stars.map<NavigationRailDestination>((Star star) { | |
| return NavigationRailDestination( | |
| icon: const Icon(Icons.article), | |
| label: Text(star.title), | |
| ); | |
| }).toList(), | |
| ); | |
| return Scaffold( | |
| body: Row( | |
| children: <Widget>[ | |
| navigationRail, | |
| const VerticalDivider(thickness: 1, width: 1), | |
| Expanded(child: view), | |
| ], | |
| ), | |
| ); | |
| } | |
| final Widget bottomNavigationBar = BottomNavigationBar( | |
| currentIndex: selectedIndex, | |
| type: BottomNavigationBarType.fixed, | |
| onTap: (int index) { | |
| setState(() { | |
| selectedIndex = index; | |
| }); | |
| }, | |
| items: stars.map<BottomNavigationBarItem>((Star star) { | |
| return BottomNavigationBarItem( | |
| icon: const Icon(Icons.article), | |
| label: star.title, | |
| ); | |
| }).toList(), | |
| ); | |
| return Scaffold( | |
| body: view, | |
| floatingActionButton: Padding( | |
| padding: const EdgeInsets.only(top: 8), | |
| child: floatingActionButton | |
| ), | |
| floatingActionButtonLocation: FloatingActionButtonLocation.startTop, | |
| bottomNavigationBar: bottomNavigationBar, | |
| ); | |
| } | |
| } | |
| class StarApp extends StatefulWidget { | |
| const StarApp({ super.key }); | |
| @override | |
| State<StarApp> createState() => _StarAppState(); | |
| } | |
| class _StarAppState extends State<StarApp> { | |
| bool darkMode = false; | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| themeMode: darkMode ? ThemeMode.dark : ThemeMode.light, | |
| theme: ThemeData( | |
| useMaterial3: true, | |
| brightness: darkMode ? Brightness.dark : Brightness.light, | |
| colorSchemeSeed: const Color(0xff6750a4), | |
| ), | |
| home: StarHome( | |
| toggleDarkMode: () { | |
| setState(() { | |
| darkMode = !darkMode; | |
| }); | |
| }, | |
| ), | |
| ); | |
| } | |
| } | |
| void main() { | |
| runApp(const StarApp()); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment