Skip to content

Commit

Permalink
Migrate IconButton to Material 3 - Part 2 (flutter#106437)
Browse files Browse the repository at this point in the history
  • Loading branch information
QuncCccccc authored and camsim99 committed Aug 10, 2022
1 parent 719e161 commit 74567b8
Show file tree
Hide file tree
Showing 4 changed files with 654 additions and 19 deletions.
14 changes: 14 additions & 0 deletions dev/tools/gen_defaults/lib/icon_button_template.dart
Expand Up @@ -35,12 +35,26 @@ class _TokenDefaultsM3 extends ButtonStyle {
if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.icon-button.disabled.icon')};
}
if (states.contains(MaterialState.selected)) {
return ${componentColor('md.comp.icon-button.selected.icon')};
}
return ${componentColor('md.comp.icon-button.unselected.icon')};
});
@override
MaterialStateProperty<Color?>? get overlayColor =>
MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.icon-button.selected.hover.state-layer')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.icon-button.selected.focus.state-layer')};
}
if (states.contains(MaterialState.pressed)) {
return ${componentColor('md.comp.icon-button.selected.pressed.state-layer')};
}
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.icon-button.unselected.hover.state-layer')};
}
Expand Down
192 changes: 192 additions & 0 deletions examples/api/lib/material/icon_button/icon_button.3.dart
@@ -0,0 +1,192 @@
// 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.

// Flutter code sample for IconButton with toggle feature

import 'package:flutter/material.dart';

void main() {
runApp(const IconButtonToggleApp());
}

class IconButtonToggleApp extends StatelessWidget {
const IconButtonToggleApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorSchemeSeed: const Color(0xff6750a4),
useMaterial3: true,
// Desktop and web platforms have a compact visual density by default.
// To see buttons with circular background on desktop/web, the "visualDensity"
// needs to be set to "VisualDensity.standard".
visualDensity: VisualDensity.standard,
),
title: 'Icon Button Types',
home: const Scaffold(
body: DemoIconToggleButtons(),
),
);
}
}

class DemoIconToggleButtons extends StatefulWidget {
const DemoIconToggleButtons({super.key});

@override
State<DemoIconToggleButtons> createState() => _DemoIconToggleButtonsState();
}

class _DemoIconToggleButtonsState extends State<DemoIconToggleButtons> {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
// Standard IconButton
children: const <Widget>[
DemoIconToggleButton(isEnabled: true),
SizedBox(width: 10),
DemoIconToggleButton(isEnabled: false),
]
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
// Filled IconButton
DemoIconToggleButton(isEnabled: true, getDefaultStyle: enabledFilledButtonStyle,),
SizedBox(width: 10),
DemoIconToggleButton(isEnabled: false, getDefaultStyle: disabledFilledButtonStyle,)
]
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
// Filled Tonal IconButton
DemoIconToggleButton(isEnabled: true, getDefaultStyle: enabledFilledTonalButtonStyle,),
SizedBox(width: 10),
DemoIconToggleButton(isEnabled: false, getDefaultStyle: disabledFilledTonalButtonStyle,),
]
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
// Outlined IconButton
DemoIconToggleButton(isEnabled: true, getDefaultStyle: enabledOutlinedButtonStyle,),
SizedBox(width: 10),
DemoIconToggleButton(isEnabled: false, getDefaultStyle: disabledOutlinedButtonStyle,),
]
),
]
),
);
}
}

class DemoIconToggleButton extends StatefulWidget {
const DemoIconToggleButton({required this.isEnabled, this.getDefaultStyle, super.key});

final bool isEnabled;
final ButtonStyle? Function(bool, ColorScheme)? getDefaultStyle;

@override
State<DemoIconToggleButton> createState() => _DemoIconToggleButtonState();
}

class _DemoIconToggleButtonState extends State<DemoIconToggleButton> {
bool selected = false;

@override
Widget build(BuildContext context) {
final ColorScheme colors = Theme.of(context).colorScheme;
final VoidCallback? onPressed = widget.isEnabled
? () {
setState(() {
selected = !selected;
});
}
: null;
ButtonStyle? style;
if (widget.getDefaultStyle != null) {
style = widget.getDefaultStyle!(selected, colors);
}

return IconButton(
isSelected: selected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: onPressed,
style: style,
);
}
}

ButtonStyle enabledFilledButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
foregroundColor: selected ? colors.onPrimary : colors.primary,
backgroundColor: selected ? colors.primary : colors.surfaceVariant,
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
hoverColor: selected ? colors.onPrimary.withOpacity(0.08) : colors.primary.withOpacity(0.08),
focusColor: selected ? colors.onPrimary.withOpacity(0.12) : colors.primary.withOpacity(0.12),
highlightColor: selected ? colors.onPrimary.withOpacity(0.12) : colors.primary.withOpacity(0.12),
);
}

ButtonStyle disabledFilledButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
);
}

ButtonStyle enabledFilledTonalButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
foregroundColor: selected ? colors.onSecondaryContainer : colors.onSurfaceVariant,
backgroundColor: selected ? colors.secondaryContainer : colors.surfaceVariant,
hoverColor: selected ? colors.onSecondaryContainer.withOpacity(0.08) : colors.onSurfaceVariant.withOpacity(0.08),
focusColor: selected ? colors.onSecondaryContainer.withOpacity(0.12) : colors.onSurfaceVariant.withOpacity(0.12),
highlightColor: selected ? colors.onSecondaryContainer.withOpacity(0.12) : colors.onSurfaceVariant.withOpacity(0.12),
);
}

ButtonStyle disabledFilledTonalButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
);
}

ButtonStyle enabledOutlinedButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
backgroundColor: selected ? colors.inverseSurface : null,
hoverColor: selected ? colors.onInverseSurface.withOpacity(0.08) : colors.onSurfaceVariant.withOpacity(0.08),
focusColor: selected ? colors.onInverseSurface.withOpacity(0.12) : colors.onSurfaceVariant.withOpacity(0.12),
highlightColor: selected ? colors.onInverseSurface.withOpacity(0.12) : colors.onSurface.withOpacity(0.12),
side: BorderSide(color: colors.outline),
).copyWith(
foregroundColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return colors.onInverseSurface;
}
if (states.contains(MaterialState.pressed)) {
return colors.onSurface;
}
return null;
}),
);
}

ButtonStyle disabledOutlinedButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: selected ? colors.onSurface.withOpacity(0.12) : null,
side: selected ? null : BorderSide(color: colors.outline.withOpacity(0.12)),
);
}

0 comments on commit 74567b8

Please sign in to comment.