【问题标题】:How to call items from JSON API and added to TabBar - Flutter如何从 JSON API 调用项目并添加到 TabBar - Flutter
【发布时间】:2020-01-23 09:11:08
【问题描述】:

我想创建(新闻应用),我在网站上有一个类别列表,我关注了这个documentation,所以我需要将网站的类别添加到我的TabBar,就像这张图片:

我该怎么做?

我想将方向从左到右更改为从右到左,我该怎么做?

代码:

Category Class:

import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<Category> fetchCatgeory() async {
  final response = await http.get("url");

  if (response.statusCode == 200) {
    return Category.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed to load category');
  }
}

class Category {
  final int id;
  final String title;

  Category({this.id, this.title});

  factory Category.fromJson(Map<String, dynamic> json) {
    return Category (
      id: json['id'],
      title: json['title'],
    );
  }

}

HomePage Class:

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:munaw3_news/extra/json_file.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();

  final Future<Category> catg;

  HomePage({Key key, this.catg}) : super(key: key);

}

class _HomePageState extends State<HomePage> {

  _HomePageState();

  int a = 0;
  Future<Category> catg;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    catg = fetchCatgeory();
  }
  bool isPressed = false;

  _pressed() {
    var newVal = true;
    if(isPressed) {
      newVal = false;
    } else {
      newVal = true;
    }

    setState((){
      isPressed = newVal;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: DefaultTabController(
        length: catg.toString().length,
        child: Scaffold(
          appBar: AppBar(
            title: Image.asset('assets/logo.png', fit: BoxFit.cover,),
            centerTitle: true,
            backgroundColor: Colors.grey[900],
            bottom: TabBar(

              tabs: [
                // Tab(text: catg[0],),
                // Tab(text: catg[1],),
                // Tab(text: catg[2],),
                // Tab(text: catg[3],)
              ],
            ),
      ),
      body: TabBarView(

        children: [
          // Tab(text: catg[0],),
          // Tab(text: catg[1],),
          // Tab(text: catg[2],),
          // Tab(text: catg[3],)
        ],

      ),
      bottomNavigationBar: BottomAppBar(
        clipBehavior: Clip.antiAlias,
        elevation: 0,
        color: Colors.grey[900],
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Container(
              height: 5,
              width: double.infinity,
              color: Colors.grey[900],
            ),
            Padding(
              padding: const EdgeInsets.only(left: 8, right: 8),
              child: Container(
                height: 60,
                child: Align(
                  alignment: FractionalOffset.center,
                  child: new Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      IconButton(icon: Icon(Icons.info), color: Colors.grey[600], iconSize: 30,
                                  disabledColor: Colors.white,
                                  onPressed: a==3 ? null : () => setState(() {
                                    a=3;
                                  })),

                      IconButton(icon: Icon(Icons.local_mall), color: Colors.grey[600], iconSize: 30,
                                  disabledColor: Colors.white,
                                  onPressed: a==2 ? null : () => setState(() {
                                    a=2;
                                  })),

                      IconButton(icon: Icon(Icons.bookmark), color: Colors.grey[600], iconSize: 30,
                                  disabledColor: Colors.white,
                                  onPressed: a==1 ? null : () => setState(() {
                                    a=1;
                                  })),

                      IconButton(icon: Icon(Icons.home), color: Colors.grey[600], iconSize: 30,
                                  disabledColor: Colors.white,
                                  onPressed: a==0 ? null : () => setState(() {
                                    a=0;
                                  })),
                    ],
                  ),
                ),
              ),
            ),

          ],
        ),
      ),
      ),),

    );
  }
}

【问题讨论】:

  • 你找到解决办法了吗?
  • 不...! :(@莎拉

标签: json flutter dart


【解决方案1】:

我解决了,先创建一个文件命名为category.dart,并在一个文件中创建一个类:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class Category {
  int id;
  String title;

  Category({
    this.id,
    this.title,
  });

  static Future<List<Category>> getCategories() async {
    http.Response response = await http.get("JSON API Url");

    List<Category> list = [];

    try {
      if (response.statusCode == 200) {
        Map<String, dynamic> map = json.decode(response.body);

        for (var map in map['categories']) {
          list.add(Category(id: map['id'], title: map['title']));
        }
      }
    } catch (e, _) {
      debugPrint(e.toString());
    }
    return list;
  }
}

并创建一个文件名list_news.dart:

import 'package:flutter/material.dart';
import 'package:munaw3_app/model/category.dart';

class ListNews extends StatefulWidget {
  ListNews({Key key}) : super(key: key);

  @override
  _ListNewsState createState() => _ListNewsState();
}

class _ListNewsState extends State<ListNews> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Category>>(
      future: Category.getCategories(),
      builder: (c, s) {
        if (s.hasData) {
          List<Tab> tabs = new List<Tab>();

          for (int i = 0; i < s.data.length; i++) {
            tabs.add(Tab(
              child: Text(
                s.data[i].title,
                style: TextStyle(color: Colors.white),
              ),
            ));
          }
          return DefaultTabController(
            length: s.data.length,
            child: Scaffold(
              appBar: AppBar(
                title: Image.asset('assets/logo.png', fit: BoxFit.cover),
                backgroundColor: Colors.grey[900],
                bottom: TabBar(
                  isScrollable: true,
                  tabs: tabs,
                ),
              ),
            ),
          );
        }
        if (s.hasError) print(s.error.toString());
        return Scaffold(
          body: Center(
              child: Text(s.hasError ? s.error.toString() : "Loading...")),
        );
      },
    );
  }
}

最后,对于TabBar 的方向,您应该更改应用程序的本地化以支持任何国家并支持从右到左 (RTL),首先转到 pubspec.yaml 和新的 pub in (dependencies):

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

最后回到main.dart文件并添加这些代码:

import 'package:flutter/material.dart';
import 'package:munaw3_app/views/list_news.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

void main() => runApp(MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
      ],
      supportedLocales: [const Locale("ar", "AE")], // Here you can add any language you need
      home: ListNews(),
    ));

【讨论】:

    【解决方案2】:

    首先,您将 JSON 数据(类别)存储在列表中的某个位置,对吗?然后您需要设置您的TabController,以便它可以与更新的数据同步。这是一个简化的示例:

    您可能需要更改为:

    class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
    

    然后,假设 Tabs/TabBarViews 将使用您从 API 调用中检索到的内容进行初始化:

    List<Widget> myTabs = [...];
    List<Widget> myTabsContent = [...];
    

    您需要创建自己的TabController,而不是使用DefaultTabController,并在void initState() 中对其进行初始化:

    TabController myTabController;
    
    @override
    void initState() {
      super.initState();
      var lastIndex = myTabs.length - 1;
      myTabController = new TabController(
          vsync: this,
          length: myTabs.length,
          initialIndex: lastIndex
      );
    }
    

    您的 Widget 构建的简化版本如下所示,因此请根据需要进行修改:

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          bottom: TabBar(
            isScrollable: true,
            controller: myTabController,
            tabs: myTabs.toList(),
          ),
        ),
    
        body: TabBarView(
          controller: myTabController,
          children: myTabsContent.toList(),
        ),
      );
    }
    

    至于这个:

    “我想将方向从左到右改为从右到 左,我该怎么做?”

    如果我理解正确,这基本上是initialIndex,如果您希望选择器位于最右侧的选项卡上,请将其设置为最后一个索引。

    【讨论】:

      猜你喜欢
      • 2020-12-30
      • 2018-12-19
      • 1970-01-01
      • 2018-08-25
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      相关资源
      最近更新 更多