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