简体   繁体   English

flutter 如何基于 null 条件创建 TabBarView

[英]flutter how to create a TabBarView base on null condition

I have a JSON file like this:我有一个像这样的 JSON 文件:

[
  {
    "name": "A",
    "tabX": ["AX1","AX2"],
    "tabY": null
  },
  {
    "name": "B",
    "tabX": null,
    "tabY": ["BY1","BY2"]
  },
  {
    "name": "C",
    "tabX": ["CX1","CX2"],
    "tabY": ["CY1","CY2"]
  }
]

I want to create 3 TabView:我想创建 3 个 TabView:

  1. The "All" tab shows all “全部”选项卡显示所有
  2. Tab "TabX" will show the elements that tabX has a value, if tabY == null will not include选项卡“TabX”将显示tabX具有值的元素,如果tabY == null 将不包括
  3. Tab "TabY" will show the elements that tabY has a value, if tabX == null will not include Tab "TabY" 将显示tabY有值的元素,如果tabX == null 将不包括

在此处输入图像描述

So please help me, this is full code:所以请帮助我,这是完整的代码:

import 'package:flutter/material.dart';
import 'dart:convert';

List<Json> jsonFromJson(String str) => List<Json>.from(json.decode(str).map((x) => Json.fromJson(x)));

String jsonToJson(List<Json> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Json {
  Json({
    this.name,
    this.tabX,
    this.tabY,
  });

  String name;
  List<String> tabX;
  List<String> tabY;

  factory Json.fromJson(Map<String, dynamic> json) => Json(
        name: json["name"] == null ? null : json["name"],
        tabX: json["tabX"] == null ? null : List<String>.from(json["tabX"].map((x) => x)),
        tabY: json["tabY"] == null ? null : List<String>.from(json["tabY"].map((x) => x)),
      );

  Map<String, dynamic> toJson() => {
        "name": name == null ? null : name,
        "tabX": tabX == null ? null : List<dynamic>.from(tabX.map((x) => x)),
        "tabY": tabY == null ? null : List<dynamic>.from(tabY.map((x) => x)),
      };
}

class JsonServices {
  static Future<List<Json>> getData() {
    String jsonString = '''
[
  {
    "name": "A",
    "tabX": ["AX1","AX2"],
    "tabY": null
  },
  {
    "name": "B",
    "tabX": null,
    "tabY": ["BY1","BY2"]
  },
  {
    "name": "C",
    "tabX": ["CX1","CX2"],
    "tabY": ["CY1","CY2"]
  }
]
    ''';

    return Future.value(jsonFromJson(jsonString));
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Json> _json = [];
  @override
  void initState() {
    super.initState();
    setState(() {
      JsonServices.getData().then((data) {
        setState(() {
          _json = data;
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(text: 'ALL'),
                Tab(text: 'TabX'),
                Tab(text: 'TabY'),
              ],
            ),
          ),
          body: TabBarView(children: [
            Tab(child: TabItemWidget(j: _json,),),
            Tab(text: 'TabX'), // pls help
            Tab(text: 'TabY'), // pls help
          ],),
        ),
      ),
    );
  }
}

class TabItemWidget extends StatelessWidget {
  final List<Json> j;

  const TabItemWidget({Key key, this.j}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Column(children: [
      for(Json j in j)
      Row(
        children: [
          Expanded(child: Text('${j.name}: ')),
          if(j.tabX != null) Expanded(child: Text(j.tabX.reduce((value, element) => '$value - $element'))),
          if(j.tabY != null) Expanded(child: Text(j.tabY.reduce((value, element) => '$value - $element')))
        ],
      )
    ],);
  }
}


You can filter the list before passing in:您可以在传入之前过滤列表:

// Only when tabX != null
_json.where((element) => element.tabX != null).toList()

// Only when tabY != null
_json.where((element) => element.tabY != null).toList()

To display only the appropriate value for that tab, we can use an enum and pass it in. It's always a good idea to use enum when we have more than 2 modes of display要仅显示该选项卡的适当值,我们可以使用enum并将其传入。当我们有超过 2 种显示模式时,使用enum总是一个好主意

enum DisplayMode { all, onlyX, onlyY }

The TabItemWidget would now be: TabItemWidget现在是:

class TabItemWidget extends StatelessWidget {
  final List<Json> j;
  final DisplayMode mode;

  const TabItemWidget({Key key, this.j, this.mode = DisplayMode.all})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        for (Json j in j)
          Row(
            children: [
              Expanded(child: Text('${j.name}: ')),
              if (j.tabX != null && !(mode == DisplayMode.onlyY))
                Expanded(
                    child: Text(j.tabX
                        .reduce((value, element) => '$value - $element'))),
              if (j.tabY != null && !(mode == DisplayMode.onlyX))
                Expanded(
                    child: Text(
                        j.tabY.reduce((value, element) => '$value - $element')))
            ],
          )
      ],
    );
  }
}

The TabBarView would now be: TabBarView现在是:

body: TabBarView(
    children: [
      Tab(
        child: TabItemWidget(
          j: _json,
        ),
      ),
      Tab(
        child: TabItemWidget(
          j: _json.where((element) => element.tabX != null).toList(),
          mode: DisplayMode.onlyX,
        ),
      ),
      // pls help
      Tab(
        child: TabItemWidget(
          j: _json.where((element) => element.tabY != null).toList(),
          mode: DisplayMode.onlyY,
        ),
      ),
      // pls help
    ],
  )

Result:结果:
在此处输入图像描述

This code is not beautiful but it works (null safety):这段代码并不漂亮,但它可以工作(空安全):

import 'package:flutter/material.dart';
import 'dart:convert';

 List<Json> jsonFromJson(String str) => List<Json>.from(json.decode(str).map((x) =>                
 Json.fromJson(x)));

 String jsonToJson(List<Json> data) => json.encode(List<dynamic>.from(data.map((x) => 
 x.toJson())));

 class Json {
   Json({
     this.name,
     this.tabX,
     this.tabY,
   });

   String? name;
   List<String>? tabX;
   List<String>? tabY;

   factory Json.fromJson(Map<String, dynamic> json) => Json(
     name: json["name"] == null ? null : json["name"],
    tabX: json["tabX"] == null ? null : List<String>.from(json["tabX"].map((x) => 
     x)),
    tabY: json["tabY"] == null ? null : List<String>.from(json["tabY"].map((x) => x)),
   );

   Map<String, dynamic> toJson() => {
    "name": name == null ? null : name,
    "tabX": (tabX == null)? null : List<dynamic>.from(tabX!.map((x) => x)),
    "tabY": (tabY == null) ? null : List<dynamic>.from(tabY!.map((x) => x)),
  };
}

class JsonServices {
  static Future<List<Json>> getData() {
    String jsonString = '''
[
  {
    "name": "A",
    "tabX": ["AX1","AX2"],
    "tabY": null
  },
  {
    "name": "B",
   "tabX": null,
    "tabY": ["BY1","BY2"]
  },
  {
    "name": "C",
    "tabX": ["CX1","CX2"],
    "tabY": ["CY1","CY2"]
  }
]
    ''';

    return Future.value(jsonFromJson(jsonString));
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Json> _json = [];
  @override
  void initState() {
    super.initState();
    setState(() {
      JsonServices.getData().then((data) {
        setState(() {
          _json = data;
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(text: 'ALL'),
                Tab(text: 'TabX'),
                Tab(text: 'TabY'),
              ],
            ),
          ),
          body: TabBarView(children: [
            Tab(child: TabItemWidget(j: _json,),),
            Tab(child: TabItemWidget2(j: _json,),), // pls help
            Tab(child: TabItemWidget3(j: _json,),), // pls help
          ],),
        ),
      ),
    );
  }
}

class TabItemWidget extends StatelessWidget {
  final List<Json> j;


  TabItemWidget({Key? key, required this.j}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      for(Json j in j)
        Row(
          children: [
            Expanded(child: Text('${j.name}: ')),
            if(j.tabX != null) Expanded(child: Text(j.tabX!.reduce((value, element) => 
 '$value - $element'))),
            if(j.tabY != null) Expanded(child: Text(j.tabY!.reduce((value, element) => 
'$value - $element')))
          ],
        )
    ],);
  }
}
class TabItemWidget2 extends StatelessWidget {
  final List<Json> j;

  const TabItemWidget2({Key? key, required this.j}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    print(j.where((element) => element.tabX != null).toString());
    var jForTabX = j.where((element) => element.tabX != null);

    return Column(children: [
      for(Json j in jForTabX)
        Row(
          children: [
            Expanded(child: Text('${j.name}: ')),
            if(j.tabX != null && j.tabY == null) Expanded(child: 
Text(j.tabX!.reduce((value, element) => '$value - $element'))),
            if(j.tabY != null) Expanded(child: Text(j.tabX!.reduce((value, element) => 
'$value - $element')))
          ],
        )
    ],);
  }
}

class TabItemWidget3 extends StatelessWidget {
  final List<Json> j;

  const TabItemWidget3({Key? key, required this.j}) : super(key: key);
  @override
  Widget build(BuildContext context) {

    var jForTabY = j.where((element) => element.tabY != null);

    return Column(children: [
      for(Json j in jForTabY)
        Row(
          children: [
            Expanded(child: Text('${j.name}: ')),
            if(j.tabX != null && j.tabX == null) Expanded(child: 
 Text(j.tabX!.reduce((value, element) => '$value - $element'))),
           if(j.tabY != null) Expanded(child: Text(j.tabY!.reduce((value, element) => 
 '$value - $element')))
          ],
        )
    ],);
  }
}

You can improve que quality of this code.您可以提高此代码的质量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM