// Copyright 2016 The Chromium 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/foundation.dart'; import 'package:flutter/widgets.dart'; import 'colors.dart'; import 'icons.dart'; import 'list_tile.dart'; import 'theme.dart'; import 'theme_data.dart'; /// This enum is deprecated. Please use [ListTileTheme] instead. enum MaterialListType { /// A list tile that contains a single line of text. oneLine, /// A list tile that contains a [CircleAvatar] followed by a single line of text. oneLineWithAvatar, /// A list tile that contains two lines of text. twoLine, /// A list tile that contains three lines of text. threeLine, } /// This constant is deprecated. The [ListTile] class sizes itself based on /// its content and [ListTileTheme]. @deprecated Map<MaterialListType, double> kListTileExtent = const <MaterialListType, double>{ MaterialListType.oneLine: 48.0, MaterialListType.oneLineWithAvatar: 56.0, MaterialListType.twoLine: 72.0, MaterialListType.threeLine: 88.0, }; const Duration _kExpand = const Duration(milliseconds: 200); /// This class is deprecated. Please use [ListTile] instead. @deprecated class TwoLevelListItem extends StatelessWidget { /// Creates an item in a two-level list. const TwoLevelListItem({ Key key, this.leading, @required this.title, this.trailing, this.enabled: true, this.onTap, this.onLongPress }) : assert(title != null), super(key: key); /// A widget to display before the title. /// /// Typically a [CircleAvatar] widget. final Widget leading; /// The primary content of the list item. /// /// Typically a [Text] widget. final Widget title; /// A widget to display after the title. /// /// Typically an [Icon] widget. final Widget trailing; /// Whether this list item is interactive. /// /// If false, this list item is styled with the disabled color from the /// current [Theme] and the [onTap] and [onLongPress] callbacks are /// inoperative. final bool enabled; /// Called when the user taps this list item. /// /// Inoperative if [enabled] is false. final GestureTapCallback onTap; /// Called when the user long-presses on this list item. /// /// Inoperative if [enabled] is false. final GestureLongPressCallback onLongPress; @override Widget build(BuildContext context) { final TwoLevelList parentList = context.ancestorWidgetOfExactType(TwoLevelList); assert(parentList != null); return new SizedBox( height: kListTileExtent[parentList.type], child: new ListTile( leading: leading, title: title, trailing: trailing, enabled: enabled, onTap: onTap, onLongPress: onLongPress ) ); } } /// This class is deprecated. Please use [ExpansionTile] instead. @deprecated class TwoLevelSublist extends StatefulWidget { /// Creates an item in a two-level list that can expand and collapse. const TwoLevelSublist({ Key key, this.leading, @required this.title, this.backgroundColor, this.onOpenChanged, this.children: const <Widget>[], }) : super(key: key); /// A widget to display before the title. /// /// Typically a [CircleAvatar] widget. final Widget leading; /// The primary content of the list item. /// /// Typically a [Text] widget. final Widget title; /// Called when the sublist expands or collapses. /// /// When the sublist starts expanding, this function is called with the value /// true. When the sublist starts collapsing, this function is called with /// the value false. final ValueChanged<bool> onOpenChanged; /// The widgets that are displayed when the sublist expands. /// /// Typically [TwoLevelListItem] widgets. final List<Widget> children; /// The color to display behind the sublist when expanded. final Color backgroundColor; @override _TwoLevelSublistState createState() => new _TwoLevelSublistState(); } @deprecated class _TwoLevelSublistState extends State<TwoLevelSublist> with SingleTickerProviderStateMixin { AnimationController _controller; CurvedAnimation _easeOutAnimation; CurvedAnimation _easeInAnimation; ColorTween _borderColor; ColorTween _headerColor; ColorTween _iconColor; ColorTween _backgroundColor; Animation<double> _iconTurns; bool _isExpanded = false; @override void initState() { super.initState(); _controller = new AnimationController(duration: _kExpand, vsync: this); _easeOutAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeOut); _easeInAnimation = new CurvedAnimation(parent: _controller, curve: Curves.easeIn); _borderColor = new ColorTween(begin: Colors.transparent); _headerColor = new ColorTween(); _iconColor = new ColorTween(); _iconTurns = new Tween<double>(begin: 0.0, end: 0.5).animate(_easeInAnimation); _backgroundColor = new ColorTween(); _isExpanded = PageStorage.of(context)?.readState(context) ?? false; if (_isExpanded) _controller.value = 1.0; } @override void dispose() { _controller.dispose(); super.dispose(); } void _handleOnTap() { setState(() { _isExpanded = !_isExpanded; if (_isExpanded) _controller.forward(); else _controller.reverse(); PageStorage.of(context)?.writeState(context, _isExpanded); }); if (widget.onOpenChanged != null) widget.onOpenChanged(_isExpanded); } Widget buildList(BuildContext context, Widget child) { return new Container( decoration: new BoxDecoration( color: _backgroundColor.evaluate(_easeOutAnimation), border: new Border( top: new BorderSide(color: _borderColor.evaluate(_easeOutAnimation)), bottom: new BorderSide(color: _borderColor.evaluate(_easeOutAnimation)) ) ), child: new Column( children: <Widget>[ IconTheme.merge( data: new IconThemeData(color: _iconColor.evaluate(_easeInAnimation)), child: new TwoLevelListItem( onTap: _handleOnTap, leading: widget.leading, title: new DefaultTextStyle( style: Theme.of(context).textTheme.subhead.copyWith(color: _headerColor.evaluate(_easeInAnimation)), child: widget.title ), trailing: new RotationTransition( turns: _iconTurns, child: const Icon(Icons.expand_more) ) ) ), new ClipRect( child: new Align( heightFactor: _easeInAnimation.value, child: new Column(children: widget.children) ) ) ] ) ); } @override Widget build(BuildContext context) { final ThemeData theme = Theme.of(context); _borderColor.end = theme.dividerColor; _headerColor ..begin = theme.textTheme.subhead.color ..end = theme.accentColor; _iconColor ..begin = theme.unselectedWidgetColor ..end = theme.accentColor; _backgroundColor ..begin = Colors.transparent ..end = widget.backgroundColor ?? Colors.transparent; return new AnimatedBuilder( animation: _controller.view, builder: buildList ); } } /// This class is deprecated. Please use [ListView] and [ListTileTheme] instead. @deprecated class TwoLevelList extends StatelessWidget { /// Creates a scrollable list of items that can expand and collapse. /// /// The [type] argument must not be null. const TwoLevelList({ Key key, this.children: const <Widget>[], this.type: MaterialListType.twoLine, this.padding, }) : assert(type != null), super(key: key); /// The widgets to display in this list. /// /// Typically [TwoLevelListItem] or [TwoLevelSublist] widgets. final List<Widget> children; /// The kind of [ListTile] contained in this list. final MaterialListType type; /// The amount of space by which to inset the children inside the viewport. final EdgeInsetsGeometry padding; @override Widget build(BuildContext context) { return new ListView( padding: padding, shrinkWrap: true, children: KeyedSubtree.ensureUniqueKeysForList(children), ); } }