我正在实现一个步进器,其中的内容显示选择列表。根据步骤在屏幕上的位置,滚动条会将标题移出视图,仅在点击时显示列表的一部分。从UX的角度来看,这是不合适的。
我已经尝试按照小部件注释中的建议将物理更改为ClampingScrollPhysics(),但这不能解决问题。下面是该程序的简化版本,可帮助其他人重新创建-只需粘贴到flutter演示项目中即可。
我还更新了flutter:-)
_MyHomePageState类扩展状态{
static YourAge yourAge = YourAge();
static Widget _ageSelector = CustomSelectorFromList(
selections: yourAge.valueList,
initialSelection: yourAge.currentSelectionIndex,
onSelectionChanged:
(int choice) {
yourAge.value = yourAge.valueList[choice];
});
List<Step> _listSteps = [
Step(title: Text("Step 1"),
content: _ageSelector,),
Step(title: Text("Step 2"),
content: _ageSelector,),
Step(title: Text("Step 3"),
content: _ageSelector,),
Step(title: Text("Step 4"),
content: _ageSelector,),
Step(title: Text("Step 5"),
content: _ageSelector,),
Step(title: Text("Step 6"),
content: _ageSelector,),
Step(title: Text("Step 7"),
content: _ageSelector,),
];
static int _currentStep = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
Expanded(
child: Container(
child: Stepper(
steps: _listSteps,
physics: ClampingScrollPhysics(),
currentStep: _currentStep,
onStepTapped: (step){
setState(() {
_currentStep = step;
});
},),
),
),
],
)
);
}
}
abstract class DiscreteParameter{
final String _yourValueKey;
final List<String> _valueList;
final String _defaultValue;
DiscreteParameter(this._yourValueKey, this._valueList,this._defaultValue);
String _value;
String get value => _value;
set value(String value) {
_value = value;
}
int get currentSelectionIndex => _valueList.indexOf(_value);
set currentSelectionIndex(int index) => (){
_value = _valueList[index];
};
List<String> get valueList => _valueList;
}
class YourAge extends DiscreteParameter{
static String _yourAgeKey = 'yourAge';
YourAge():super(_yourAgeKey, _ageList, aged26to35);
//String _yourAge = aged26to35;
static const String agedUpto15 = "<15";
static const String aged16to25 = "16-25";
static const String aged26to35 = "26-35";
static const String aged36to45 = "36-45";
static const String aged46to55 = "46-55";
static const String aged56to65 = "56-65";
static const String aged66plus = "66+";
static const List<String> _ageList = [agedUpto15, aged16to25, aged26to35, aged36to45, aged46to55, aged56to65, aged66plus];
}
class CustomSelectorFromList extends StatefulWidget {
final Function(int) onSelectionChanged;
final int initialSelection;
final List<String> selections;
@override
_CustomSelectorFromListState createState() => _CustomSelectorFromListState(
onSelectionChanged: onSelectionChanged,
initialSelection: initialSelection,
selections: selections);
//include a callback function to parent to react to state change
CustomSelectorFromList({Key key, @required this.selections, @required this.onSelectionChanged, @required this.initialSelection});
}
class _CustomSelectorFromListState extends State<CustomSelectorFromList> {
Function(int) onSelectionChanged;
final int initialSelection;
final List<String> selections;
int _listLength;
int _value = 0;
_CustomSelectorFromListState({Key key, @required this.selections, @required this.onSelectionChanged, @required this.initialSelection}){
//state is preserved so can be set from user "shared preferences"
_value = initialSelection;
_listLength = selections.length;
}
@override
Widget build(BuildContext context) {
//debugPrint("list length: ${selections.length.toString()}");
return Wrap(
direction: Axis.vertical,
children: List<Widget>.generate(
_listLength, (int index) {
return ChoiceChip(
label: Text("${selections[index]}",
style: TextStyle(
color: _value==index ? Colors.white70 : Colors.blueGrey
),),
selectedColor: Colors.blueGrey,
disabledColor: Colors.white70,
//labelPadding: EdgeInsets.symmetric(),
padding: const EdgeInsets.all(10),
selected: _value == index,
onSelected: (bool selected) {
setState(() {
_value = selected ? index : null;
});
//callback to parent widget - index of selected item
onSelectionChanged(index);
},
);
},
).toList(),
);
}
}
我希望步骤的onTap滚动以显示下面的步骤标题和内容。但是,如果我显示第1步,请不要滚动并单击第2步,则标题会跳出视图,仅显示底部的几个选择筹码,迫使用户将列表向下拖动以查看所有选项。
答案 0 :(得分:0)
给定的行为是使用以下组合的结果:Column
=> Expanded
=> Stepper
。 Column
小部件本身不可滚动,因此,如果子级超过高度(例如屏幕高度),则将导致像素溢出。因此,Column
=> Stepper
的组合将无法获得预期的结果。之所以有效,是因为您用Stepper
小部件包裹了Expanded
,该小部件可用于实现RenderFlex
的小部件(Stepper
会做什么)并将使用所有可用的小部件渲染它的空间,并在必要时使其可滚动。因此,基本上,您可以只将Stepper
用作Scaffold
的主体,就可以达到相同的目的-只是想指出一点,因为这可能会对您有所帮助!
查看Stepper
的{{1}}回调的实现,它将调用onStepTapped
函数以确保其中一个Scrollable.ensureVisible(...)
的内容在显示后可见点击。因此,颤振会在这一点上避免出现给定的行为。似乎在这种情况下将要设置的偏移量是由于Step
=> Column
=> Expanded
的组合计算错误的。
为了获得更好的结果,我尝试了另一种方法:Stepper
=> ListView
并将Stepper
的{{1}}设置为scrollPhysics
,因此{{ 1}}不会消耗任何滚动输入,并且Stepper
被用作主滚动处理程序:
NeverScrollableScrollPhysics