- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个自定义步进器。将整个flift / lib复制到我的项目中。然后,我复制了stepper.dart并编辑了必要的部分。结果如下:
// 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/widgets.dart';
import 'package:immunity/src/material/button_theme.dart';
import 'package:immunity/src/material/colors.dart';
import 'package:immunity/src/material/debug.dart';
import 'package:immunity/src/material/flat_button.dart';
import 'package:immunity/src/material/icons.dart';
import 'package:immunity/src/material/ink_well.dart';
import 'package:immunity/src/material/material.dart';
import 'package:immunity/src/material/material_localizations.dart';
import 'package:immunity/src/material/theme.dart';
import 'package:immunity/src/material/typography.dart';
// TODO(dragostis): Missing functionality:
// * mobile horizontal mode with adding/removing steps
// * alternative labeling
// * stepper feedback in the case of high-latency interactions
/// The state of a [Step] which is used to control the style of the circle and
/// text.
///
/// See also:
///
/// * [Step]
enum StepStateCustom {
/// A step that displays its index in its circle.
indexed,
/// A step that displays a pencil icon in its circle.
editing,
/// A step that displays a tick icon in its circle.
complete,
/// A step that is disabled and does not to react to taps.
disabled,
/// A step that is currently having an error. e.g. the use has submitted wrong
/// input.
error,
}
/// Defines the [Stepper]'s main axis.
enum StepperTypeCustom {
/// A vertical layout of the steps with their content in-between the titles.
vertical,
/// A horizontal layout of the steps with their content below the titles.
horizontal,
}
const TextStyle _kStepStyle = TextStyle(
fontSize: 12.0,
color: Colors.white,
);
const Color _kErrorLight = Colors.red;
final Color _kErrorDark = Colors.red.shade400;
const Color _kCircleActiveLight = Colors.white;
const Color _kCircleActiveDark = Colors.black87;
const Color _kDisabledLight = Colors.black38;
const Color _kDisabledDark = Colors.white30;
const double _kStepSize = 24.0;
const double _kTriangleHeight = _kStepSize * 0.866025; // Triangle height. sqrt(3.0) / 2.0
/// A material step used in [Stepper]. The step can have a title and subtitle,
/// an icon within its circle, some content and a state that governs its
/// styling.
///
/// See also:
///
/// * [Stepper]
/// * <https://material.google.com/components/steppers.html>
@immutable
class StepCustom {
/// Creates a step for a [Stepper].
///
/// The [title], [content], and [state] arguments must not be null.
const StepCustom({
@required this.title,
this.subtitle,
@required this.content,
this.state = StepStateCustom.indexed,
this.isActive = false,
}) : assert(title != null),
assert(content != null),
assert(state != null);
/// The title of the step that typically describes it.
final Widget title;
/// The subtitle of the step that appears below the title and has a smaller
/// font size. It typically gives more details that complement the title.
///
/// If null, the subtitle is not shown.
final Widget subtitle;
/// The content of the step that appears below the [title] and [subtitle].
///
/// Below the content, every step has a 'continue' and 'cancel' button.
final Widget content;
/// The state of the step which determines the styling of its components
/// and whether steps are interactive.
final StepStateCustom state;
/// Whether or not the step is active. The flag only influences styling.
final bool isActive;
}
/// A material stepper widget that displays progress through a sequence of
/// steps. Steppers are particularly useful in the case of forms where one step
/// requires the completion of another one, or where multiple steps need to be
/// completed in order to submit the whole form.
///
/// The widget is a flexible wrapper. A parent class should pass [currentStep]
/// to this widget based on some logic triggered by the three callbacks that it
/// provides.
///
/// See also:
///
/// * [Step]
/// * <https://material.google.com/components/steppers.html>
class StepperCustom extends StatefulWidget {
/// Creates a stepper from a list of steps.
///
/// This widget is not meant to be rebuilt with a different list of steps
/// unless a key is provided in order to distinguish the old stepper from the
/// new one.
///
/// The [steps], [type], and [currentStep] arguments must not be null.
StepperCustom({
Key key,
@required this.steps,
this.type = StepperTypeCustom.vertical,
this.currentStep = 0,
this.onStepTapped,
this.onStepContinue,
this.onStepCancel,
}) : assert(steps != null),
assert(type != null),
assert(currentStep != null),
assert(0 <= currentStep && currentStep < steps.length),
super(key: key);
/// The steps of the stepper whose titles, subtitles, icons always get shown.
///
/// The length of [steps] must not change.
final List<StepCustom> steps;
/// The type of stepper that determines the layout. In the case of
/// [StepperTypeCustom.horizontal], the content of the current step is displayed
/// underneath as opposed to the [StepperTypeCustom.vertical] case where it is
/// displayed in-between.
final StepperTypeCustom type;
/// The index into [steps] of the current step whose content is displayed.
final int currentStep;
/// The callback called when a step is tapped, with its index passed as
/// an argument.
final ValueChanged<int> onStepTapped;
/// The callback called when the 'continue' button is tapped.
///
/// If null, the 'continue' button will be disabled.
final VoidCallback onStepContinue;
/// The callback called when the 'cancel' button is tapped.
///
/// If null, the 'cancel' button will be disabled.
final VoidCallback onStepCancel;
@override
_StepperCustomState createState() => _StepperCustomState();
}
class _StepperCustomState extends State<StepperCustom> with TickerProviderStateMixin {
List<GlobalKey> _keys;
final Map<int, StepStateCustom> _oldStates = <int, StepStateCustom>{};
@override
void initState() {
super.initState();
_keys = List<GlobalKey>.generate(
widget.steps.length,
(int i) => GlobalKey(),
);
for (int i = 0; i < widget.steps.length; i += 1)
_oldStates[i] = widget.steps[i].state;
}
@override
void didUpdateWidget(StepperCustom oldWidget) {
super.didUpdateWidget(oldWidget);
assert(widget.steps.length == oldWidget.steps.length);
for (int i = 0; i < oldWidget.steps.length; i += 1)
_oldStates[i] = oldWidget.steps[i].state;
}
bool _isFirst(int index) {
return index == 0;
}
bool _isLast(int index) {
return widget.steps.length - 1 == index;
}
bool _isCurrent(int index) {
return widget.currentStep == index;
}
bool _isDark() {
return Theme.of(context).brightness == Brightness.dark;
}
Widget _buildLine(bool visible) {
return Container(
width: visible ? 1.0 : 0.0,
height: 16.0,
color: Colors.grey.shade400,
);
}
Widget _buildCircleChild(int index, bool oldState) {
final StepStateCustom state = oldState ? _oldStates[index] : widget.steps[index].state;
final bool isDarkActive = _isDark() && widget.steps[index].isActive;
assert(state != null);
switch (state) {
case StepStateCustom.indexed:
case StepStateCustom.disabled:
return Text(
'${index + 1}',
style: isDarkActive ? _kStepStyle.copyWith(color: Colors.black87) : _kStepStyle,
);
case StepStateCustom.editing:
return Icon(
Icons.edit,
color: isDarkActive ? _kCircleActiveDark : _kCircleActiveLight,
size: 18.0,
);
case StepStateCustom.complete:
return Icon(
Icons.check,
color: isDarkActive ? _kCircleActiveDark : _kCircleActiveLight,
size: 18.0,
);
case StepStateCustom.error:
return const Text('!', style: _kStepStyle);
}
return null;
}
Color _circleColor(int index) {
final ThemeData themeData = Theme.of(context);
if (!_isDark()) {
return widget.steps[index].isActive ? themeData.primaryColor : Colors.black38;
} else {
return widget.steps[index].isActive ? themeData.accentColor : themeData.backgroundColor;
}
}
Widget _buildCircle(int index, bool oldState) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 8.0),
width: _kStepSize,
height: _kStepSize,
child: AnimatedContainer(
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
decoration: BoxDecoration(
color: _circleColor(index),
shape: BoxShape.circle,
),
child: Center(
child: _buildCircleChild(index, oldState && widget.steps[index].state == StepStateCustom.error),
),
),
);
}
Widget _buildTriangle(int index, bool oldState) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 8.0),
width: _kStepSize,
height: _kStepSize,
child: Center(
child: SizedBox(
width: _kStepSize,
height: _kTriangleHeight, // Height of 24dp-long-sided equilateral triangle.
child: CustomPaint(
painter: _TrianglePainter(
color: _isDark() ? _kErrorDark : _kErrorLight,
),
child: Align(
alignment: const Alignment(0.0, 0.8), // 0.8 looks better than the geometrical 0.33.
child: _buildCircleChild(index, oldState && widget.steps[index].state != StepStateCustom.error),
),
),
),
),
);
}
Widget _buildIcon(int index) {
if (widget.steps[index].state != _oldStates[index]) {
return AnimatedCrossFade(
firstChild: _buildCircle(index, true),
secondChild: _buildTriangle(index, true),
firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
sizeCurve: Curves.fastOutSlowIn,
crossFadeState: widget.steps[index].state == StepStateCustom.error ? CrossFadeState.showSecond : CrossFadeState.showFirst,
duration: kThemeAnimationDuration,
);
} else {
if (widget.steps[index].state != StepStateCustom.error)
return _buildCircle(index, false);
else
return _buildTriangle(index, false);
}
}
Widget _buildVerticalControls() {
Color cancelColor;
switch (Theme.of(context).brightness) {
case Brightness.light:
cancelColor = Colors.black54;
break;
case Brightness.dark:
cancelColor = Colors.white70;
break;
}
assert(cancelColor != null);
final ThemeData themeData = Theme.of(context);
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
return Container(
margin: const EdgeInsets.only(top: 16.0),
child: ConstrainedBox(
constraints: const BoxConstraints.tightFor(height: 48.0),
child: Row(
children: <Widget>[
FlatButton(
onPressed: widget.onStepContinue,
color: _isDark() ? themeData.backgroundColor : themeData.primaryColor,
textColor: Colors.white,
textTheme: ButtonTextTheme.normal,
child: Text(localizations.continueButtonLabel),
),
Container(
margin: const EdgeInsetsDirectional.only(start: 8.0),
child: FlatButton(
onPressed: widget.onStepCancel,
textColor: cancelColor,
textTheme: ButtonTextTheme.normal,
child: Text(localizations.cancelButtonLabel),
),
),
],
),
),
);
}
TextStyle _titleStyle(int index) {
final ThemeData themeData = Theme.of(context);
final TextTheme textTheme = themeData.textTheme;
assert(widget.steps[index].state != null);
switch (widget.steps[index].state) {
case StepStateCustom.indexed:
case StepStateCustom.editing:
case StepStateCustom.complete:
return textTheme.body2;
case StepStateCustom.disabled:
return textTheme.body2.copyWith(
color: _isDark() ? _kDisabledDark : _kDisabledLight
);
case StepStateCustom.error:
return textTheme.body2.copyWith(
color: _isDark() ? _kErrorDark : _kErrorLight
);
}
return null;
}
TextStyle _subtitleStyle(int index) {
final ThemeData themeData = Theme.of(context);
final TextTheme textTheme = themeData.textTheme;
assert(widget.steps[index].state != null);
switch (widget.steps[index].state) {
case StepStateCustom.indexed:
case StepStateCustom.editing:
case StepStateCustom.complete:
return textTheme.caption;
case StepStateCustom.disabled:
return textTheme.caption.copyWith(
color: _isDark() ? _kDisabledDark : _kDisabledLight
);
case StepStateCustom.error:
return textTheme.caption.copyWith(
color: _isDark() ? _kErrorDark : _kErrorLight
);
}
return null;
}
Widget _buildHeaderText(int index) {
final List<Widget> children = <Widget>[
AnimatedDefaultTextStyle(
style: _titleStyle(index),
duration: kThemeAnimationDuration,
curve: Curves.fastOutSlowIn,
child: widget.steps[index].title,
),
];
if (widget.steps[index].subtitle != null)
children.add(
Container(
margin: const EdgeInsets.only(top: 2.0),
child: AnimatedDefaultTextStyle(
style: _subtitleStyle(index),
duration: kThemeAnimationDuration,
curve: Curves.fastOutSlowIn,
child: widget.steps[index].subtitle,
),
),
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: children
);
}
Widget _buildVerticalHeader(int index) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 24.0),
child: Row(
children: <Widget>[
Column(
children: <Widget>[
// Line parts are always added in order for the ink splash to
// flood the tips of the connector lines.
_buildLine(!_isFirst(index)),
_buildIcon(index),
_buildLine(!_isLast(index)),
]
),
Container(
margin: const EdgeInsetsDirectional.only(start: 12.0),
child: _buildHeaderText(index)
)
]
)
);
}
Widget _buildVerticalBody(int index) {
return Stack(
children: <Widget>[
PositionedDirectional(
start: 24.0,
top: 0.0,
bottom: 0.0,
child: SizedBox(
width: 24.0,
child: Center(
child: SizedBox(
width: _isLast(index) ? 0.0 : 1.0,
child: Container(
color: Colors.grey.shade400,
),
),
),
),
),
AnimatedCrossFade(
firstChild: Container(height: 0.0),
secondChild: Container(
margin: const EdgeInsetsDirectional.only(
start: 60.0,
end: 24.0,
bottom: 24.0,
),
child: Column(
children: <Widget>[
widget.steps[index].content,
_buildVerticalControls(),
],
),
),
firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
sizeCurve: Curves.fastOutSlowIn,
crossFadeState: _isCurrent(index) ? CrossFadeState.showSecond : CrossFadeState.showFirst,
duration: kThemeAnimationDuration,
),
],
);
}
Widget _buildVertical() {
final List<Widget> children = <Widget>[];
for (int i = 0; i < widget.steps.length; i += 1) {
children.add(
Column(
key: _keys[i],
children: <Widget>[
InkWell(
onTap: widget.steps[i].state != StepStateCustom.disabled ? () {
// In the vertical case we need to scroll to the newly tapped
// step.
Scrollable.ensureVisible(
_keys[i].currentContext,
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
);
if (widget.onStepTapped != null)
widget.onStepTapped(i);
} : null,
child: _buildVerticalHeader(i)
),
_buildVerticalBody(i)
]
)
);
}
return ListView(
shrinkWrap: true,
children: children,
);
}
Widget _buildHorizontal() {
final List<Widget> children = <Widget>[];
for (int i = 0; i < widget.steps.length; i += 1) {
children.add(
InkResponse(
onTap: widget.steps[i].state != StepStateCustom.disabled ? () {
if (widget.onStepTapped != null)
widget.onStepTapped(i);
} : null,
child: Row(
children: <Widget>[
Container(
height: 72.0,
child: Center(
child: _buildIcon(i),
),
),
Container(
margin: const EdgeInsetsDirectional.only(start: 12.0),
child: _buildHeaderText(i),
),
],
),
),
);
if (!_isLast(i)) {
children.add(
Expanded(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 8.0),
height: 1.0,
color: Colors.grey.shade400,
),
),
);
}
}
return Column(
children: <Widget>[
Material(
elevation: 2.0,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 24.0),
child: Row(
children: children,
),
),
),
Expanded(
child: ListView(
padding: const EdgeInsets.all(24.0),
children: <Widget>[
AnimatedSize(
curve: Curves.fastOutSlowIn,
duration: kThemeAnimationDuration,
vsync: this,
child: widget.steps[widget.currentStep].content,
),
_buildVerticalControls(),
],
),
),
],
);
}
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
assert(() {
if (context.ancestorWidgetOfExactType(StepperCustom) != null)
throw FlutterError(
'Steppers must not be nested. The material specification advises '
'that one should avoid embedding steppers within steppers. '
'https://material.google.com/components/steppers.html#steppers-usage\n'
);
return true;
}());
assert(widget.type != null);
switch (widget.type) {
case StepperTypeCustom.vertical:
return _buildVertical();
case StepperTypeCustom.horizontal:
return _buildHorizontal();
}
return null;
}
}
// Paints a triangle whose base is the bottom of the bounding rectangle and its
// top vertex the middle of its top.
class _TrianglePainter extends CustomPainter {
_TrianglePainter({
this.color
});
final Color color;
@override
bool hitTest(Offset point) => true; // Hitting the rectangle is fine enough.
@override
bool shouldRepaint(_TrianglePainter oldPainter) {
return oldPainter.color != color;
}
@override
void paint(Canvas canvas, Size size) {
final double base = size.width;
final double halfBase = size.width / 2.0;
final double height = size.height;
final List<Offset> points = <Offset>[
Offset(0.0, height),
Offset(base, height),
Offset(halfBase, 0.0),
];
canvas.drawPath(
Path()..addPolygon(points, true),
Paint()..color = color,
);
}
}
最佳答案
错误是:Stepper widgets require a Material widget ancestor
。
实际上,您的小部件需要具有Material祖先。只需将其包裹在Material中,如下所示:
Material(
child: YourStepper
)
关于dart - Flutter:“自定义步进器”小部件需要“ Material ”小部件祖先,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52928383/
我想向一些用户公开一个 Web 部件,但不是所有用户。如何在“添加 Web 部件”弹出窗口中显示或隐藏 Web 部件?我想通过代码来做到这一点,我希望使用 SharePoint 角色来实现这一点。 最
我无法创建两个以上的 StatusBar 部分: HWND hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, "", WS_CHILD | WS_VISI
使用 SharePoint 2007,如何在编辑页面模式下允许将 CEWP 添加到“添加 Web 部件”对话框的选择菜单?目前,我只能添加公告、日历、链接、共享文档、任务,但我无法添加 CEWP。我可
哪个 Web 部件以及如何配置它以查看来自不同网站集的列表? 请注意,我不想查看页面,而是查看列表。例如,在单独的网站集下查看来自不同团队网站的公告。 预先感谢您的帮助。 最佳答案 Data Form
以下是我在 FeatureDeactivation 事件处理程序中添加的代码片段。我无法获得删除 System.Web.UI.WebControls.WebParts 类型的 webpart 的解决方
我一直在尝试跟踪来自以下方面的信息: Long URL clipped to stop breaking the page 和 http://msdn.microsoft.com/en-us/libr
我想创建一个自定义 Web 部件,它具有 1 个以上的筛选器 Web 部件,并且可以在运行时/设计时连接到报表查看器 Web 部件(集成模式)。 我为此搜索了很多,但找不到一种方法来让单个 Web 部
我正在尝试创建一个 Web 部件,使用户无需离开 AllItems.aspx 页面即可编辑项目。 Web 部件应具有与 EditForm.aspx 页面类似的功能。 我已经使用 ConnectionC
这些年发布的许多应用程序都有新的 GUI 部件。iTunes 或 Twitter.app 中垂直布局的最小、最大和关闭按钮(但最新的具有默认布局),Safari 和终端中的选项卡控件,GarageBa
在具有数据库依赖性的 WSS3 或 MOSS2007 中部署 Web 部件的最佳方法是什么? .wsp 是否应该包含创建数据库的代码,我应该将 .wsp 封装在另一个处理数据库创建的安装程序中,还是应
我在我们位于 http://sharepoint:12345 的 moss 服务器上创建了一个新的共享点站点并毫无问题地向其添加了 CQWP。 我有一个指向同一台服务器的域名。所以我指向了http:/
在官方 Office 2007 站点中有许多对筛选器 Web 部件的引用。当我尝试添加其中之一时,我的 Sharepoint 中的 Web 部件列表没有显示任何筛选器 Web 部件。 如果有人遇到相同
我被要求在 Sharepoint 中创建一个 Web 部件,列出用户在网站集中访问的最后 10 个文档。 我的客户想要一种快速的方式让用户访问文档,这样他们就不必翻遍文件夹结构来查找文档,因为大多数时
我需要使用 C# 以编程方式将 SharePoint Web 部件“站点用户”添加到页面。 我知道如何添加 Web 部件,但如何从 Share Point 获取“站点用户”Web 部件?我不知道如何实
我正在使用 MEF 在我的应用程序中加载插件。一切正常,但我希望在将新部件放入我的应用程序文件夹时发现它们。这可能吗? DirectoryCatalog 有一个 Changed 事件,但我不确定它是如
我有一个 Winforms 桌面应用程序正在加载具有相同接口(interface)类型的多个 MEF 部件。 问题:当我尝试加载多个相同类型时,出现以下异常: 组成保持不变。由于以下错误,更改被拒绝:
我有一个内容查询 Web 部件,它按内容类型对网站集进行查询。我已按内容类型对其进行了分组,因此我有: -- Agenda (Content Type) ----Agenda #1 ----Agend
考虑以下 SharePoint 站点层次结构: - Site Collection - Site1 - Subsite1 - AnotherSubsite1
好吧,在我的 SharePoint (2013) 网站中,我制作了一个简单的 JavaScript Web 部件,每五分钟刷新一次页面。我去调整时间,在刷新前输入等待时间的地方退格,然后不假思索地退出
我不知道 Sharepoint 脚本,我的同事也不知道 JavaScript。他使用了他在 http://www.wonderlaura.com/Lists/Posts/Post.aspx?ID=22
我是一名优秀的程序员,十分优秀!