#flutter #flutter-listview #flutter-dropdownbutton
Вопрос:
У меня не хватает ListView
максимум 10 предметов. Каждый элемент списка будет содержать a DropDownButton
, который будет содержать около 1 тыс. DropDownMenuItems
для выбора.
В родном Android я смог реализовать тот, который работал очень плавно, но с помощью Flutter требуется некоторое время, чтобы создать представление списка, которое приводит к зависанию пользовательского интерфейса.
В моем случае мне нужно будет перестраивать представление списка при каждом изменении одного из его элементов, поэтому это будет серьезной проблемой.
Есть ли способ ускорить сборку ListView или, по крайней мере, отображать ProgressBar
его до тех пор, пока он не будет собран?
N. B: Использование --profile
конфигурации для имитации версии выпуска значительно повышает производительность, но все равно ощущается замораживание.
Вот мой пример кода, который вы можете напрямую скопировать/вставить, если хотите проверить его самостоятельно.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool showList = false;
final List<DropdownMenuItem<int>> selections = List.generate(
1000,
(index) => DropdownMenuItem<int>(
value: index,
child: Text("$index"),
),
);
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
width: double.infinity,
child: Column(
children: [
ElevatedButton(
child: Text("toggle list visibility"),
onPressed: () {
setState(() {
showList = !showList;
});
},
),
Expanded(
child: showList
? ListView.builder(
cacheExtent: 2000,
itemCount: 10,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Container(
height: 200,
color: Colors.green,
child: Column(
children: [
Text("List Item: $index"),
DropdownButton<int>(
onChanged: (i) {},
value: 1,
items: selections,
),
],
),
),
),
);
})
: Text("List Not Built"),
),
],
),
),
),
);
}
}
Комментарии:
1. Вы должны использовать CustomScrollView со списком SliverList вместо ListView.
Ответ №1:
Раскрывающийся список загрузки при нажатии на кнопку.
Добавьте этот виджет в свой основной список
InkWell(
onTap: () {
showDialog(
context: context,
builder: (_) {
return VendorListAlert(selectVendor: selectVendorTap);
});
},
child: // create a widget, looks like your drop down
),
Событие касания ручки
void selectVendorTap(pass your model){
// logic
}
Образец для пользовательского оповещения
Нет необходимости создавать изменяемый виджет, неизменяемый виджет лучше.
class VendorListAlert extends StatefulWidget {
final Function selectVendor;
const VendorListAlert({Key key, this.selectVendor}) : super(key: key);
@override
_VendorListAlertState createState() => _VendorListAlertState();
}
class _VendorListAlertState extends State<VendorListAlert> {
List<UserModel> _searchVendor = [];
@override
void initState() {
super.initState();
_searchVendor = List.from(ypModel);
}
@override
Widget build(BuildContext context) {
return AlertDialog(
content: Container(
width: width,
child: ListView.builder(
shrinkWrap: true,
itemCount: _searchVendor.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: InkWell(
onTap: () {
widget.selectVendor(_searchVendor[index]);
Navigator.pop(context);
},
child:
),
);
},
),
),
);
}
}
Комментарии:
1. Гений! Мне также больше не нужно указывать cacheExtent для представления списка. До этого мне приходилось это делать для того, чтобы сделать прокрутку плавной. Означает ли это, что «Кнопка выпадающего списка» не может лениво создавать свой контент?