简体   繁体   中英

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:

在此处输入图像描述

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:

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 :

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):

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

And finally back to main.dart file and add these code:

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? Then you'll need to setup your TabController so that it can sync with the updated data. 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:

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

Instead of using DefaultTabController , you'll need to create your own TabController , and initialize it in 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:

@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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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