Flutter:如何使用弯曲的抽屉自定义

时间:2020-07-13 16:26:26

标签: flutter flutter-layout flutter-animation

enter image description here

我正在尝试定制具有某种弯曲样式的抽屉,这可能吗?

如果是这样,有例子吗?

2 个答案:

答案 0 :(得分:1)

Flutter在构建用户界面方面提供了极大的灵活性,您可以结合使用各种小部件来获得所需的输出。

我演示了您要实现的目标。我添加了代码并输出(作为图像)

class SO extends StatelessWidget {

  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      // bottom padding 
      endDrawer: Padding(
        padding: const EdgeInsets.only(bottom: 80),
        child: ClipRRect(
          // give it your desired border radius
          borderRadius: BorderRadius.only(
            bottomLeft: Radius.circular(250),
          ),
          // wrap with a sizedbox for a custom width [for more flexibility]
          child: SizedBox(
            width: 200,
            child: Drawer(
              // your widgets goes here
              child: ...,
            ),
          ),
        ),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20),
          child: SizedBox(
            height: 50,
            child: FlatButton(
              color: Colors.blue,
              // open the drawer
              onPressed: () {
                _scaffoldKey.currentState.openEndDrawer();
              },
              child: Center(
                child: Text('Open Drawer'),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

输出:

enter image description here

答案 1 :(得分:0)

如果您检查抽屉的代码,您会发现它只是一个ConstraindedBox和一个Material(以及语义),因此也许您可以复制相同的代码并对其进行一些细微更改材料的形状

class MyDrawer extends StatelessWidget {
  /// Creates a material design drawer.
  ///
  /// Typically used in the [Scaffold.drawer] property.
  ///
  /// The [elevation] must be non-negative.
  const MyDrawer({
    Key key,
    this.elevation = 16.0,
    this.child,
    this.semanticLabel,
    this.isEndDrawer = false
  }) : assert(elevation != null && elevation >= 0.0),
        super(key: key);
 
  /// Added so the shape changes left or right depending the position of the drawer
  final bool isEndDrawer;

  /// The z-coordinate at which to place this drawer relative to its parent.
  ///
  /// This controls the size of the shadow below the drawer.
  ///
  /// Defaults to 16, the appropriate elevation for drawers. The value is
  /// always non-negative.
  final double elevation;

  /// The widget below this widget in the tree.
  ///
  /// Typically a [SliverList].
  ///
  /// {@macro flutter.widgets.child}
  final Widget child;

  /// The semantic label of the dialog used by accessibility frameworks to
  /// announce screen transitions when the drawer is opened and closed.
  ///
  /// If this label is not provided, it will default to
  /// [MaterialLocalizations.drawerLabel].
  ///
  /// See also:
  ///
  ///  * [SemanticsConfiguration.namesRoute], for a description of how this
  ///    value is used.
  final String semanticLabel;

  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMaterialLocalizations(context));
    String label = semanticLabel;
    switch (Theme.of(context).platform) {
      case TargetPlatform.iOS:
      case TargetPlatform.macOS:
        label = semanticLabel;
        break;
      case TargetPlatform.android:
      case TargetPlatform.fuchsia:
      case TargetPlatform.linux:
      case TargetPlatform.windows:
        label = semanticLabel ?? MaterialLocalizations.of(context)?.drawerLabel;
    }
    return Semantics(
      scopesRoute: true,
      namesRoute: true,
      explicitChildNodes: true,
      label: label,
      child: Align(
        alignment: isEndDrawer ? Alignment.topRight : Alignment.topLeft,
        child: FractionallySizedBox(
          heightFactor: 0.95,
          child: ConstrainedBox(
            constraints: const BoxConstraints.expand(width: 304.0), //304 is the kWidth of the Drawer
            child: Material(
              elevation: elevation,
              child: child,
              shape: RoundedRectangleBorder( //Add this ShapeBorder to the Material
                borderRadius: isEndDrawer ?
                  BorderRadius.only(bottomLeft: Radius.circular(220))
                  : BorderRadius.only(bottomRight: Radius.circular(220)),
                side: BorderSide.none
              ),
            ),
          )
        )
      ),
    );
  }
}

然后在脚手架中像常规抽屉一样使用它

Scaffold(
  endDrawer: MyDrawer(
    isEndDrawer: true,
    child: ... your child widget
  ),
  drawer: MyDrawer(
    child: ... your child widget
  ),
)

如果您比较代码,我只是将isEndDrawerAlignFractionallySizedBox和形状添加到Material

enter image description here