Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import 'dart:ui';
- import 'package:flutter/material.dart';
- import 'package:flutter/scheduler.dart';
- import 'package:lucide_icons/lucide_icons.dart';
- import 'package:flutter_gen/gen_l10n/app_localizations.dart';
- import 'package:pomotimer/app_text_style.dart';
- import '../../generated/l10n.dart';
- class HomePage extends StatelessWidget {
- const HomePage({super.key});
- @override
- Widget build(BuildContext context) {
- var theme = Theme.of(context);
- return Scaffold(
- backgroundColor: theme.scaffoldBackgroundColor,
- appBar: TopBar(theme),
- body: const HomeBody(),
- );
- }
- }
- class TopBar extends AppBar {
- TopBar(ThemeData theme, {super.key})
- : super(
- backgroundColor: Colors.transparent,
- leading: Container(
- margin: const EdgeInsets.only(left: 15),
- child: IconButton(
- iconSize: 25,
- tooltip: S.current.settingBtnTooltip,
- icon: Icon(LucideIcons.settings,
- color: theme.colorScheme.onBackground),
- onPressed: () {
- // TODO 跳转到设置
- },
- ),
- ));
- }
- class HomeBody extends StatelessWidget {
- const HomeBody({super.key});
- @override
- Widget build(BuildContext context) {
- return Container(
- constraints: const BoxConstraints.expand(),
- child: Center(
- child: Container(
- constraints: const BoxConstraints.tightFor(width: 300, height: 500),
- child: const TimerController()),
- ),
- );
- }
- }
- class TimerController extends StatefulWidget {
- const TimerController({super.key});
- @override
- State<StatefulWidget> createState() => _TimerControllerState();
- }
- class _TimerControllerState extends State<TimerController> {
- var selected = 0;
- @override
- Widget build(BuildContext context) {
- var theme = Theme.of(context);
- return Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- AttributeSwitcher(
- selected: selected,
- onSelected: (selected) => debugPrint('selected: $selected'),
- ),
- ],
- );
- }
- }
- class AttributeSwitcher extends StatefulWidget {
- AttributeSwitcher(
- {super.key, required this.selected, required this.onSelected}) {
- if (selected < 0 || selected > 2) {
- throw Exception('selected must be in [0, 2]');
- }
- }
- final int selected;
- final void Function(int) onSelected;
- @override
- State<AttributeSwitcher> createState() => _AttributeSwitcherState();
- }
- class _AttributeSwitcherState extends State<AttributeSwitcher> {
- int _selected = 0;
- @override
- void initState() {
- super.initState();
- _selected = widget.selected;
- }
- void _updateSelected(int selected) {
- setState(() {
- _selected = selected;
- });
- widget.onSelected(selected);
- }
- Widget _createSticky({
- required double posX,
- required double posY,
- required double height,
- required double width,
- required ColorScheme colorScheme,
- }) {
- return AnimatedPositioned(
- duration: const Duration(milliseconds: 500),
- top: posY,
- left: posX,
- child: UnconstrainedBox(
- child: AnimatedContainer(
- height: height,
- width: width,
- decoration: BoxDecoration(
- color: colorScheme.primaryContainer,
- borderRadius: BorderRadius.circular(80),
- ),
- duration: const Duration(milliseconds: 500),
- ),
- ));
- }
- OverlayEntry _createRow({required List<GlobalKey> btnKeys}) {
- return OverlayEntry(
- builder: (context) => Row(
- mainAxisSize: MainAxisSize.min,
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- AttributeBtn(
- btnKey: btnKeys[0], text: '专注', onPressed: () => _updateSelected(0)),
- const AttributeSplitter(),
- AttributeBtn(
- btnKey: btnKeys[1],
- text: '小休息',
- onPressed: () => _updateSelected(1),
- ),
- const AttributeSplitter(),
- AttributeBtn(
- btnKey: btnKeys[2],
- text: '大休息',
- onPressed: () => _updateSelected(2),
- ),
- ],
- ),
- );
- }
- @override
- Widget build(BuildContext context) {
- ThemeData theme = Theme.of(context);
- ColorScheme colorScheme = theme.colorScheme;
- TextTheme textTheme = theme.textTheme;
- List<GlobalKey> btnKeys = [GlobalKey(), GlobalKey(), GlobalKey()];
- List<Offset> btnPos = [];
- List<Size> btnSize = [];
- GlobalKey overlayKey = GlobalKey();
- OverlayEntry row = _createRow(btnKeys: btnKeys);
- SchedulerBinding.instance.addPostFrameCallback((_) {
- OverlayState state = overlayKey.currentState as OverlayState;
- if (overlayKey.currentContext == null) {
- throw Exception('overlayKey.currentContext is null');
- }
- var overlayPos =
- (overlayKey.currentContext?.findRenderObject() as RenderBox)
- .localToGlobal(Offset.zero);
- for (var element in btnKeys) {
- if (element.currentContext == null) {
- throw Exception('element.currentContext is null');
- }
- var readerBox = element.currentContext?.findRenderObject() as RenderBox;
- var readerSize = readerBox.size;
- var readerPos =
- readerBox.localToGlobal(Offset(-overlayPos.dx, -overlayPos.dy));
- btnPos.add(readerPos);
- btnSize.add(readerSize);
- }
- state.insert(OverlayEntry(builder: (context) {
- return _createSticky(
- posX: btnPos[_selected].dx,
- posY: btnPos[_selected].dy,
- height: btnSize[_selected].height,
- width: btnSize[_selected].width,
- colorScheme: colorScheme,
- );
- }), below: row);
- });
- return SizedBox(
- width: 300,
- height: 50,
- child: Overlay(key: overlayKey, initialEntries: [row]),
- );
- }
- }
- class AttributeBtn extends StatelessWidget {
- const AttributeBtn(
- {super.key, this.btnKey, this.onPressed, required this.text});
- final void Function()? onPressed;
- final String text;
- final GlobalKey? btnKey;
- @override
- Widget build(BuildContext context) {
- ThemeData theme = Theme.of(context);
- TextTheme textTheme = theme.textTheme;
- return Container(
- margin: const EdgeInsets.symmetric(horizontal: 5),
- child: ConstrainedBox(
- constraints: const BoxConstraints(
- maxHeight: double.infinity,
- minHeight: 0,
- maxWidth: double.infinity,
- minWidth: 70,
- ),
- child: TextButton(
- key: btnKey,
- onPressed: onPressed,
- child: Text(
- text,
- style: AppTextStyle.generateWithTextStyle(textTheme.bodyLarge!),
- )),
- ),
- );
- }
- }
- class AttributeSplitter extends StatelessWidget {
- const AttributeSplitter({super.key});
- @override
- Widget build(BuildContext context) {
- ThemeData theme = Theme.of(context);
- ColorScheme colorScheme = theme.colorScheme;
- return Container(
- decoration: BoxDecoration(
- color: colorScheme.surface,
- shape: BoxShape.circle,
- ),
- height: 4,
- width: 4,
- );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement