简体   繁体   English

如何从 JSON API 调用项目并添加到 TabBar - Flutter

[英]How to call items from JSON API and added to TabBar - Flutter

I want to create (News App), I have a list of category in the website, I followed this documentation , so I need to add website's category to my TabBar , exactly like this image:我想创建(新闻应用程序),我在网站中有一个类别列表,我遵循了这个文档,所以我需要将网站的类别添加到我的TabBar中,就像这张图片一样:

在此处输入图像描述

How can I do that?我怎样才能做到这一点?

And I want to change direction from left to right to from right to left, How can I do that?我想从左到右改变方向,从右到左,我该怎么做?

Code:代码:

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;
                                  })),
                    ],
                  ),
                ),
              ),
            ),

          ],
        ),
      ),
      ),),

    );
  }
}

I solved it, first create a file named it category.dart , and in a file create a class:我解决了,首先创建一个名为category.dart的文件,然后在一个文件中创建一个 class:

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;
  }
}

And creating a file name it list_news.dart :并创建一个文件名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(), //NOT Recommended
      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...")),
        );
      },
    );
  }
}

And finally, for directional of TabBar you should change the localization of your app to support any country and support fro right to left (RTL), first go to pubspec.yaml and new pub in (dependencies):最后,对于TabBar的方向,您应该更改应用程序的本地化以支持任何国家/地区并支持从右到左(RTL),首先 go 到pubspec.yaml和新 pub in(依赖项):

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

And finally back to main.dart file and add these code:最后回到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(),
    ));

First, you're storing your JSON data, Categories, somewhere in a list, right?首先,您将 JSON 数据、类别存储在列表的某个位置,对吗? Then you'll need to setup your TabController so that it can sync with the updated data.然后你需要设置你的TabController以便它可以与更新的数据同步。 Here's a simplified example:这是一个简化的示例:

You might need to change to:您可能需要更改为:

class _HomePageState extends State<HomePage> with TickerProviderStateMixin {

Then, assuming Tabs/TabBarViews will be initialized with stuff that you've retrieved from your API call:然后,假设 Tabs/TabBarViews 将使用您从 API 调用中检索到的内容进行初始化:

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

Instead of using DefaultTabController , you'll need to create your own TabController , and initialize it in void initState() :而不是使用DefaultTabController ,您需要创建自己的TabController ,并在void initState()中对其进行初始化:

TabController myTabController;

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

A simplified version of your Widget build will look like this, so modify as needed:您的 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(),
    ),
  );
}

And as for this:至于这个:

And I want to change direction from left to right to from right to left, How can I do that? 我想从左到右改变方向,从右到左,我该怎么做?

If I understand correctly, this is basically initialIndex , set it to the last index if you want the selector to be on the right most tab.如果我理解正确,这基本上是initialIndex ,如果您希望选择器位于最右侧的选项卡上,请将其设置为最后一个索引。

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

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