首页 > 解决方案 > 点击 AppBar 中的 IconButton 以显示悬浮在 Scaffold 主体上的 TextField(带有一个小部件,而不是两个)

问题描述

AppBar有没有办法从身体上方(上方)的小部件中浮动一个盒子Scaffold?例如,如果我将我的搜索小部件放入Scaffold正文中,当我的搜索IconButton被点击时,它TextField会出现并挂在它下面的内容上:

带有搜索输入框的搜索图标

但是,理想情况下,我希望搜索图标出现在AppBar(而不是Scaffold正文)中,然后点击时,我希望输入框浮在Scaffold正文上。如果我将我的搜索小部件放入 中AppBarTextField则隐藏在Scaffold正文下方,如下所示:

AppBar 中的搜索图标在 Scaffold 后面溢出

如果你仔细看,TextField在我点击图标下方AppBar但主体上方的小边距后,您实际上可以看到focusedBorder Scaffold

在 AppBar 和 Scaffold 之间点击时的 TextField 边框

因此,您可以看到TextField隐藏在Scaffold身体后面。

我从 Flutter 文档中发现,Scaffoldbody 将其内容置于 the 之下AppBar和之后,floatingActionButton并且drawer是设计的(https://api.flutter.dev/flutter/material/Scaffold/body.html)。但是,在这个用例中使用 afloatingActionButton或 adrawer会有点麻烦。

我想我可以将TextField放在一个单独的小部件中并位于Scaffold正文中,并使用Provider/与被点击的ChangeNotifier小部件通信。但是,这将组件逻辑分成了两个地方,这看起来很混乱。我希望有人可以用最佳实践启发我或让我朝着正确的方向前进。ScaffoldIconButtonAppBar

那么,有没有一种合适的方法让一个漂浮在身体IconButton上的AppBar显示器 a ?(这似乎是一个常见的用例。)TextFieldScaffold

标签: flutterflutter-layout

解决方案


您可以使用 aStack为您的Scaffold > body

在此处输入图像描述

完整源代码:

import 'dart:math' show Random;

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(AppWidget());
}

class AppWidget extends StatelessWidget {
  const AppWidget({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => SearchModel(),
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: ThemeData(primaryColor: Color(0xfffedbd0)),
        title: 'Flutter Demo',
        home: HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<SearchModel>(
      builder: (context, searchModel, child) => Scaffold(
        appBar: AppBar(
          title: Text('SHRINE'),
          actions: [
            IconButton(
                icon: Icon(Icons.search, semanticLabel: 'search'),
                onPressed: () => searchModel.toggleVisibility()),
          ],
        ),
        body: Container(
          padding: EdgeInsets.all(16.0),
          alignment: Alignment.center,
          child: Search(),
        ),
      ),
    );
  }
}

class Search extends StatelessWidget {
  Search();

  @override
  Widget build(BuildContext context) {
    return Consumer<SearchModel>(builder: (context, searchModel, child) {
      return Stack(
        children: [
          GridView.count(
            crossAxisCount: 3,
            children: List.generate(
              30,
              (index) => Container(
                color: Color(0xaaaa0000 + 0xffffff ~/ (index + 1)),
              ),
            ),
          ),
          Positioned.fill(
            child: Align(
              alignment: Alignment.center,
              child: AnimatedOpacity(
                opacity: searchModel.isVisible ? 1.0 : 0.0,
                duration: Duration(milliseconds: 500),
                child: SizedBox(
                  width: 190.0,
                  height: 25.0,
                  child: TextField(
                    decoration: InputDecoration(
                      filled: true,
                      fillColor: Theme.of(context).primaryColor,
                      hintText: 'Enter a search term',
                      contentPadding: const EdgeInsets.symmetric(
                          horizontal: 8.0, vertical: 4.0),
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.black),
                        borderRadius: BorderRadius.circular(25.7),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: BorderSide(color: Colors.black),
                        borderRadius: BorderRadius.circular(25.7),
                      ),
                    ),
                    onChanged: (text) => searchModel.updateText(text),
                  ),
                ),
              ),
            ),
          ),
        ],
      );
    });
  }
}

class SearchModel extends ChangeNotifier {
  String text = '';
  bool isVisible = false;

  updateText(String newText) {
    text = newText;
    notifyListeners();
  }

  toggleVisibility() {
    isVisible = !isVisible;
    notifyListeners();
  }
}

推荐阅读