#flutter #expandablelistview #flutter-web
#flutter #расширяемый список просмотра #flutter-web
Вопрос:
У меня есть функциональность для реализации, где мне нужно настроить пользовательский список просмотра каждого виджета, содержащего текстовое поле и кнопку. И дочерний виджет содержит список каждого виджета, содержащий текстовое поле для ввода нового курса.
Ниже приведена функциональность.
- Шаг 1 — это статическое поле для входа в курс.
- После ввода курса нажатие на кнопку добавить в поле курс добавит список просмотра динамического виджета (родительский список просмотра) любой темы.
- После загрузки виджета темы, нажав на правую кнопку добавить, необходимо добавить дочерний listview другого динамического виджета к родительскому (дочернему listview) подтем.
- Итак, на рисунке выше 2, 4 являются родительскими listviews, а 3, 5 должны быть дочерними listviews
Ниже приведен мой код.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(debugShowCheckedModeBanner: false, home: NewCourse()));
}
class NewCourse extends StatefulWidget {
@override
_NewCourseState createState() => _NewCourseState();
}
class _NewCourseState extends State<NewCourse> {
bool isTagSelected = false;
bool isTopicCreationEnabled = false;
List<NewTopic> newTopicList = [];
addNewTopic() {
newTopicList.add(new NewTopic());
setState(() {});
}
enableTopicCreation(String txtTopicName) {
setState(() {
if (txtTopicName.length > 0) {
isTopicCreationEnabled = true;
} else {
isTopicCreationEnabled = false;
}
});
}
@override
Widget build(BuildContext context) {
var _createNewTopic;
if (isTopicCreationEnabled) {
_createNewTopic = () {
addNewTopic();
};
} else {
_createNewTopic = null;
}
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey,
title: Text('ALL COURSES'),
centerTitle: true,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
color: Colors.blueGrey,
child: Center(
child: Padding(
padding: EdgeInsets.all(20),
child: Text(
"NEW COURSE",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
fontFamily: 'CodeFont',
color: Colors.white,
),
),
),
),
),
Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 20.0,
offset: Offset(0, 10),
),
],
),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 9,
child: Container(
padding: EdgeInsets.all(8),
margin: EdgeInsets.all(8),
child: TextField(
onChanged: (text) {
enableTopicCreation(text);
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Course Name",
hintStyle: TextStyle(color: Colors.grey[400]),
),
),
),
),
Expanded(
flex: 3,
child: FlatButton(
onPressed: _createNewTopic,
child: Container(
padding: EdgeInsets.all(18),
margin: EdgeInsets.all(8),
child: Icon(
Icons.add_box,
color: isTopicCreationEnabled
? Colors.green
: Colors.blueGrey,
),
),
),
),
],
),
],
),
),
Container(
child: Expanded(
child: getAllTopicsListView(),
),
),
],
),
);
}
Widget getAllTopicsListView() {
ListView topicList = new ListView.builder(
itemCount: newTopicList.length,
itemBuilder: (context, index) {
return new ListTile(
title: new NewTopic(),
);
});
return topicList;
}
}
class NewTopic extends StatefulWidget {
@override
_NewTopicState createState() => _NewTopicState();
}
class _NewTopicState extends State<NewTopic> {
bool isSubTopicCreationEnabled = false;
List<NewSubTopic> newSubTopicList = [];
addNewSubTopic() {
setState(() {
newSubTopicList.add(new NewSubTopic());
});
}
enableSubTopicCreation(String txtTopicName) {
setState(
() {
if (txtTopicName.length > 0) {
isSubTopicCreationEnabled = true;
} else {
isSubTopicCreationEnabled = false;
}
},
);
}
@override
Widget build(BuildContext context) {
var _createNewSubTopic;
if (isSubTopicCreationEnabled) {
_createNewSubTopic = () {
addNewSubTopic();
};
} else {
_createNewSubTopic = null;
}
return Column(
children: [
Container(
margin: EdgeInsets.only(top: 20, bottom: 20, left: 10, right: 50),
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 20.0,
offset: Offset(0, 10),
),
],
),
child: Center(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 9,
child: Container(
child: TextField(
onChanged: (text) {
enableSubTopicCreation(text);
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Enter the topic",
hintStyle: TextStyle(color: Colors.grey[400]),
),
),
),
),
Expanded(
flex: 3,
child: FlatButton(
onPressed: _createNewSubTopic,
child: Container(
child: Icon(
Icons.add_box,
color: isSubTopicCreationEnabled
? Colors.green
: Colors.blueGrey,
),
),
),
),
],
),
Row(
children: <Widget>[
Container(
child: Expanded(
//child: Text("Hi There!"),
child: getAllSubTopicsListView(),
),
),
],
),
],
),
),
),
],
);
}
Widget getAllSubTopicsListView() {
ListView subTopicList = new ListView.builder(
itemCount: newSubTopicList.length,
itemBuilder: (context, index) {
return new ListTile(
title: new NewSubTopic(),
);
},
);
return subTopicList;
}
}
class NewSubTopic extends StatefulWidget {
@override
_NewSubTopicState createState() => _NewSubTopicState();
}
class _NewSubTopicState extends State<NewSubTopic> {
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
margin: EdgeInsets.only(top: 20, bottom: 20, left: 50, right: 10),
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey[400],
blurRadius: 20.0,
offset: Offset(0, 10),
),
],
),
child: Center(
child: Container(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Enter the sub topic",
hintStyle: TextStyle(color: Colors.grey[400]),
),
),
),
),
),
],
);
}
}
Вот проблема
Assertion failed: file:///C:/src/flutter/packages/flutter/lib/src/rendering/sliver_multi_box_adaptor.dart:545:12
child.hasSize
is not true
Любая помощь / предложение будут высоко оценены.
Заранее спасибо.
Ответ №1:
Вам просто нужно сжать ListViews:
ListView topicList = new ListView.builder(
shrinkWrap: true,
itemCount: newTopicList.length,
//...
ListView subTopicList = new ListView.builder(
shrinkWrap: true,
itemCount: newSubTopicList.length,
ListView — это, по сути, CustomScrollView с одним SliverList в
его свойство CustomScrollView.slivers.
Если вид прокрутки не сжимается, то вид прокрутки расширится до максимально допустимого размера в scrollDirection. Если вид прокрутки имеет неограниченные ограничения в scrollDirection, то shrinkWrap должно быть true.
Вы можете узнать больше о ListView и shrinkWrap в официальном документе.