- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我的 Flutter 应用程序中,我有一个屏幕,它是一个带有 Scaffold 小部件的 MaterialApp 作为它的主页。
这个 Scaffold 的 appBar 属性是一个 AppBar 小部件,其 actions 属性填充了一些操作和一个用于容纳其余选项的弹出菜单。
问题是,据我了解 AppBar 的 child actions
list 可以是通用小部件(它将作为操作添加)或 PopupMenuButton
的实例,在这种情况下,它将添加平台特定图标,当触发该图标时会打开 AppBar 弹出菜单。
在原生 Android 上,这不是它的工作方式。我只需要膨胀一个充满菜单项的菜单,每个项目要么可以被强制成为一个 Action ,要么被强制不是一个 Action ,或者具有特殊值“ifRoom”,这意味着“如果有空间,就成为一个 Action ,否则是弹出菜单中的一个项目”。
Flutter 中有没有一种方法可以实现这种行为,而无需编写复杂的逻辑来填充 AppBar 的“ Action ”属性?
我已经查看了 AppBar 和 PopupMenuButton 文档,到目前为止还没有解释如何做这样的事情。我可以模拟这种行为,但随后我必须实际编写一个例程来计算可用空间并相应地构建“ Action ”列表。
这是一个典型的 Android 菜单,它混合了操作和弹出菜单条目。请注意,如果有空间,“load_game”条目可以是一个 Action ,如果没有空间,它将成为一个菜单条目。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/new_game"
android:icon="@drawable/ic_new_game"
android:title="@string/new_game"
android:showAsAction="always"/>
<item android:id="@+id/load_game"
android:icon="@drawable/ic_load_game"
android:title="@string/load_game"
android:showAsAction="ifRoom"/>
<item android:id="@+id/help"
android:icon="@drawable/ic_help"
android:title="@string/help"
android:showAsAction="never" />
</menu>
AppBar(
title: Text("My Incredible Game"),
primary: true,
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
tooltip: "New Game",
onPressed: null,
),
IconButton(
icon: Icon(Icons.cloud_upload),
tooltip: "Load Game",
onPressed: null,
),
PopupMenuButton(
itemBuilder: (BuildContext context) {
return <PopupMenuEntry>[
PopupMenuItem(
child: Text("Help"),
),
];
},
)
],
)
最佳答案
开箱即用不支持此功能,但您可以复制该行为。我创建了以下小部件:
import 'package:flutter/material.dart';
class CustomActionsRow extends StatelessWidget {
final double availableWidth;
final double actionWidth;
final List<CustomAction> actions;
const CustomActionsRow({
@required this.availableWidth,
@required this.actionWidth,
@required this.actions,
});
@override
Widget build(BuildContext context) {
actions.sort(); // items with ShowAsAction.NEVER are placed at the end
List<CustomAction> visible = actions
.where((CustomAction customAction) => customAction.showAsAction == ShowAsAction.ALWAYS)
.toList();
List<CustomAction> overflow = actions
.where((CustomAction customAction) => customAction.showAsAction == ShowAsAction.NEVER)
.toList();
double getOverflowWidth() => overflow.isEmpty ? 0 : actionWidth;
for (CustomAction customAction in actions) {
if (customAction.showAsAction == ShowAsAction.IF_ROOM) {
if (availableWidth - visible.length * actionWidth - getOverflowWidth() > actionWidth) { // there is enough room
visible.insert(actions.indexOf(customAction), customAction); // insert in its given position
} else { // there is not enough room
if (overflow.isEmpty) {
CustomAction lastOptionalAction = visible.lastWhere((CustomAction customAction) => customAction.showAsAction == ShowAsAction.IF_ROOM, orElse: () => null);
if (lastOptionalAction != null) {
visible.remove(lastOptionalAction); // remove the last optionally visible action to make space for the overflow icon
overflow.add(lastOptionalAction);
overflow.add(customAction);
} // else the layout will overflow because there is not enough space for all the visible items and the overflow icon
} else {
overflow.add(customAction);
}
}
}
}
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
...visible.map((CustomAction customAction) => customAction.visibleWidget),
if (overflow.isNotEmpty) PopupMenuButton(
itemBuilder: (BuildContext context) => [
for (CustomAction customAction in overflow) PopupMenuItem(
child: customAction.overflowWidget,
)
],
)
],
);
}
}
class CustomAction implements Comparable<CustomAction> {
final Widget visibleWidget;
final Widget overflowWidget;
final ShowAsAction showAsAction;
const CustomAction({
this.visibleWidget,
this.overflowWidget,
@required this.showAsAction,
});
@override
int compareTo(CustomAction other) {
if (showAsAction == ShowAsAction.NEVER && other.showAsAction == ShowAsAction.NEVER) {
return 0;
} else if (showAsAction == ShowAsAction.NEVER) {
return 1;
} else if (other.showAsAction == ShowAsAction.NEVER) {
return -1;
} else {
return 0;
}
}
}
enum ShowAsAction {
ALWAYS,
IF_ROOM,
NEVER,
}
您需要指出所有图标(包括溢出图标)的总可用宽度,以及每个操作的宽度(它们都需要具有相同的宽度)。这是一个使用它的例子:
return Scaffold(
appBar: AppBar(
title: const Text("Title"),
actions: <Widget>[
CustomActionsRow(
availableWidth: MediaQuery.of(context).size.width / 2, // half the screen width
actionWidth: 48, // default for IconButtons
actions: [
CustomAction(
overflowWidget: GestureDetector(
onTap: () {},
child: const Text("Never 1"),
),
showAsAction: ShowAsAction.NEVER,
),
CustomAction(
visibleWidget: IconButton(
onPressed: () {},
icon: Icon(Icons.ac_unit),
),
showAsAction: ShowAsAction.ALWAYS,
),
CustomAction(
visibleWidget: IconButton(
onPressed: () {},
icon: Icon(Icons.cancel),
),
overflowWidget: GestureDetector(
onTap: () {},
child: const Text("If Room 1"),
),
showAsAction: ShowAsAction.IF_ROOM,
),
CustomAction(
visibleWidget: IconButton(
onPressed: () {},
icon: Icon(Icons.ac_unit),
),
showAsAction: ShowAsAction.ALWAYS,
),
CustomAction(
visibleWidget: IconButton(
onPressed: () {},
icon: Icon(Icons.cancel),
),
overflowWidget: GestureDetector(
onTap: () {},
child: const Text("If Room 2"),
),
showAsAction: ShowAsAction.IF_ROOM,
),
CustomAction(
overflowWidget: GestureDetector(
onTap: () {},
child: const Text("Never 2"),
),
showAsAction: ShowAsAction.NEVER,
),
],
),
],
),
);
请注意,我没有添加任何断言,但您应该始终提供
visibleWidget
对于
showAsAction
的操作是
ALWAYS
或
IF_ROOM
,并始终提供
overflowWidget
对于
showAsAction
的操作是
IF_ROOM
或
NEVER
.
CustomActionsRow
根据您的要求,例如,您可能有不同宽度的操作,在这种情况下,您需要每个
CustomAction
提供自己的宽度等。
关于android - 如何在 Flutter 中模拟 Android 的 showAsAction ="ifRoom"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55433298/
我的 Android 应用程序工具栏上的操作出现问题。 我有一个包含一些具有 app:showAsAction="ifRoom" 属性的操作的组。如果 ifRoom 的项目少于 4 个,则一切正常。但
我使用“最低要求的 SDK”API 11 创建了一个基本项目来测试 Action Bar。他们没有在栏上显示操作按钮,而是在操作溢出中结束,甚至栏是空的。我使用了以下代码。 但是当我添加以下命名空间
我正在尝试让 ActionBar 在我的应用程序上正常工作(我正在使用 ActionBarSherlock 在 Android 2.x 和 4.x 之间获得统一的 UI)。 我觉得 android:s
我的操作栏有问题,我尝试设置 search view为了得到一个可展开的搜索栏。 这很好,除了我必须使用选项 ifRoom 设置所有其他菜单项,以便在单击搜索图标时让搜索字段占据所有房间。 这部分也很
我想使用 Espresso 单击以下菜单项: 由于 ifRoom,在某些设备中,菜单在操作栏中显示为图标,而在较小的设备中,它显示在“更多选项”下。 我可以使用以下代码点击操作栏中的“保存”图标:o
我是 Android 的新手,遇到了一个似乎很常见的问题。没有一个解决方案对我有用,所以我不知道出了什么问题。 我有一个包含 2 个项目的菜单(搜索、购物),我希望搜索出现在操作栏中。但是,app:s
我正在创建一个小型应用程序并尝试在 ActionBar 上提供一个共享按钮。相关代码如下所示: list 菜单项 Activity public boolean onCreateOptionsMe
是否可以按照建议设置标志here android:showAsAction="ifRoom|withText" 以编程方式? 最佳答案 对于每个 MenuItem,执行以下操作: myMenuItem
我正在尝试向我的支持操作栏添加一些操作项。在我的 Activity 中,我还向操作栏添加了选项卡。 这是 Activity 的摘录: public class ShowEmails extends A
在我的 Flutter 应用程序中,我有一个屏幕,它是一个带有 Scaffold 小部件的 MaterialApp 作为它的主页。 这个 Scaffold 的 appBar 属性是一个 AppBar
我有一个包含以下菜单项的操作栏; 问题是我的搜索按钮没有显示在操作栏上,但文本显示在溢出中。我的操作栏有足够的空间 我正在使用 "@st
在MenuItem之后已扩展为 SearchView , 溢出菜单显示另一个搜索项。我对它的预期行为是它不会在 SearchView 时显示另一个搜索项。展开。 在MenuItem之后折叠,搜索项不再
我是一名优秀的程序员,十分优秀!