[英]Flutter : How to call Local JSON Data and added to Tabbar dinamically?
[英]How to call items from JSON API and added to TabBar - Flutter
我想創建(新聞應用程序),我在網站中有一個類別列表,我遵循了這個文檔,所以我需要將網站的類別添加到我的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;
})),
],
),
),
),
),
],
),
),
),),
);
}
}
我解決了,首先創建一個名為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;
}
}
並創建一個文件名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...")),
);
},
);
}
}
最后,對於TabBar
的方向,您應該更改應用程序的本地化以支持任何國家/地區並支持從右到左(RTL),首先 go 到pubspec.yaml
和新 pub in(依賴項):
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(),
));
首先,您將 JSON 數據、類別存儲在列表的某個位置,對嗎? 然后你需要設置你的TabController
以便它可以與更新的數據同步。 這是一個簡化的示例:
您可能需要更改為:
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
然后,假設 Tabs/TabBarViews 將使用您從 API 調用中檢索到的內容進行初始化:
List<Widget> myTabs = [...];
List<Widget> myTabsContent = [...];
而不是使用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
);
}
您的 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
,如果您希望選擇器位於最右側的選項卡上,請將其設置為最后一個索引。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.