问题描述
我正在尝试使用 Flutter 构建一个动态标签栏,该栏显示带有与我的 JSON 数据对应的标签名称的标签,然后对于每个键,我想将它的值映射为相应标签中的 ListView。从本地资产文件中检索 JSON 数据。我尝试了多种方法,但仍然出现错误。此外,ListView 的代码正在运行,我只是无法弄清楚如何使用 JSON 映射它。任何帮助将不胜感激。
这是我最后一次尝试的代码
JSON 文件
[
{
"vegetables": [
{
"name": "Potato","minorder": 1.5,"pricePerKg": 12.5,"imageUrl": "assets/images/potato.jpg","description": "Very Healthy but high fat"
},{
"name": "Cabbage","minorder": 1,"pricePerKg": 10,"imageUrl": "assets/images/cabbage.jpg","description": "Very Healthy but be aware"
},{
"name": "Lady Finger","imageUrl": "assets/images/lady_finger.jpg","description": "Very Healthy green vegetable healthy for eyesight"
},{
"name": "Spinach","imageUrl": "assets/images/spinach.jpg","description": "Very Healthy green leafy"
},{
"name": "Cauliflower","imageUrl": "assets/images/cauliflower.jpg","description": "Very Healthy keeps doctor away"
},{
"name": "Capsicum","imageUrl": "assets/images/capsicum.jpg","description": "Very Healthy and green vegetable"
}
]
},{
"Fruits": [
{
"name": "Banana","imageUrl": "assets/images/banana.jpg","description": "Very Healthy helps in gaining weight"
},{
"name": "Orange","imageUrl": "assets/images/orange.jpg","description": "Very Healthy and citrus"
},{
"name": "Apple","imageUrl": "assets/images/apple.jpg","description": "Very Healthy keeps doctor away"
}
]
},{
"Bakery": [
{
"name": "Cake",{
"name": "Cookies",{
"Fish": [
{
"name": "Gold Fish",{
"name": "Luna",{
"Poultry": [
{
"name": "White Egg",{
"name": "brown Egg",{
"name": "Chicken meat","description": "Very Healthy keeps doctor away"
}
]
}
]
Dart 代码
import 'dart:convert';
import 'package:asset_app/navigation/custom_bottom_nav_bar.dart';
import 'package:Flutter/material.dart';
class ParsingJson extends StatefulWidget {
const ParsingJson({Key key}) : super(key: key);
@override
_ParsingJsonState createState() => _ParsingJsonState();
}
class _ParsingJsonState extends State<ParsingJson> {
Future<String> jsonString;
List _cards;
Map _data;
int _initPosition = 1;
@override
void initState() {
super.initState();
jsonString = DefaultAssetBundle.of(context)
.loadString("assets/json_file/categories.json");
// .then((d) {
// _cards = json.decode(d);
// setState(() => _data = _cards[0]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("JSON parsing demo"),),body: SafeArea(
child: FutureBuilder(
future: jsonString,builder: (context,snapshot) {
if (snapshot.hasData) {
// Decode the JSON
Map newData = json.decode(snapshot.data.toString())[0];
return CustomTabView(
initPosition: _initPosition,itemCount: (newData.keys as List).length + 1,tabBuilder: (context,index) =>
Tab(text: (newData.keys.toList())[index]),pageBuilder: (context,index) =>
Center(child: Text("data[index]")),onPositionChange: (index) {
print('current position: $index');
_initPosition = index;
},onScroll: (position) => print('$position'),);
}
return CircularProgressIndicator();
})));
}
}
标签条码
import 'package:Flutter/material.dart';
class CustomTabView extends StatefulWidget {
final int itemCount;
final IndexedWidgetBuilder tabBuilder;
final IndexedWidgetBuilder pageBuilder;
final Widget stub;
final ValueChanged<int> onPositionChange;
final ValueChanged<double> onScroll;
final int initPosition;
CustomTabView({
@required this.itemCount,@required this.tabBuilder,@required this.pageBuilder,this.stub,this.onPositionChange,this.onScroll,this.initPosition,});
@override
_CustomTabsstate createState() => _CustomTabsstate();
}
class _CustomTabsstate extends State<CustomTabView>
with TickerProviderStateMixin {
TabController controller;
int _currentCount;
int _currentPosition;
@override
void initState() {
_currentPosition = widget.initPosition ?? 0;
controller = TabController(
length: widget.itemCount,vsync: this,initialIndex: _currentPosition,);
controller.addListener(onPositionChange);
controller.animation.addListener(onScroll);
_currentCount = widget.itemCount;
super.initState();
}
@override
void didUpdateWidget(CustomTabView oldWidget) {
if (_currentCount != widget.itemCount) {
controller.animation.removeListener(onScroll);
controller.removeListener(onPositionChange);
controller.dispose();
if (widget.initPosition != null) {
_currentPosition = widget.initPosition;
}
if (_currentPosition > widget.itemCount - 1) {
_currentPosition = widget.itemCount - 1;
_currentPosition = _currentPosition < 0 ? 0 : _currentPosition;
if (widget.onPositionChange is ValueChanged<int>) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
widget.onPositionChange(_currentPosition);
}
});
}
}
_currentCount = widget.itemCount;
setState(() {
controller = TabController(
length: widget.itemCount,);
controller.addListener(onPositionChange);
controller.animation.addListener(onScroll);
});
} else if (widget.initPosition != null) {
controller.animateto(widget.initPosition);
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
controller.animation.removeListener(onScroll);
controller.removeListener(onPositionChange);
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (widget.itemCount < 1) return widget.stub ?? Container();
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,children: <Widget>[
Container(
alignment: Alignment.center,child: TabBar(
isScrollable: true,controller: controller,labelColor: Theme.of(context).primaryColor,unselectedLabelColor: Theme.of(context).hintColor,indicator: Boxdecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).primaryColor,width: 2,tabs: List.generate(
widget.itemCount,(index) => widget.tabBuilder(context,index),Expanded(
child: TabBarView(
controller: controller,children: List.generate(
widget.itemCount,(index) => widget.pageBuilder(context,],);
}
onPositionChange() {
if (!controller.indexIsChanging) {
_currentPosition = controller.index;
if (widget.onPositionChange is ValueChanged<int>) {
widget.onPositionChange(_currentPosition);
}
}
}
onScroll() {
if (widget.onScroll is ValueChanged<double>) {
widget.onScroll(controller.animation.value);
}
}
}
错误- 构建 FutureBuilder(dirty,state: _FutureBuilderState#6d218) 时抛出了以下 _CastError: 类型 '_CompactIterable' 不是类型转换中类型 'List' 的子类型
解决方法
这里错了:
itemCount: (newData.keys as List).length + 1,
因为 newData.keys
是 _CompactIterable
所以不能强制转换为列表
=> itemCount: newData.keys.toList().length + 1,