#flutter #dart
#трепетание #дротик
Вопрос:
Я работаю над проектом flutter, где у меня есть 3 вкладки на панели вкладок. На вкладке 1 и вкладке 2 есть списки, показывающие некоторые данные с помощью ListView. При нажатии на элемент списка я хочу передать некоторую строку на вкладку 3 и показать вкладку 3.
Ниже приведен код моей домашней страницы:
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
TabController controller;
@override
void initState() {
super.initState();
controller = new TabController(vsync: this, length: 3);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {},
child: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text("InstaPost"),
backgroundColor: Colors.black45,
bottom: TabBar(
tabs: [
Tab(
text: "Tab 1",
),
Tab(text: "Tab 2"),
Tab(text: "Tab 3"),
// Tab(text: "My Posts")
],
),
),
body: TabBarView(
children: <Widget>[
Tab1(),
Tab2(),
Tab3(),
],
),
),
),
);
}
}
Итак, при запуске приложения первым экраном будет вкладка 1, на которой отображается список имен. Код приведен ниже
class _HashtagPageState extends State<HashtagPage> {
Future<dynamic> getLists() async {
// get list
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {},
child: FutureBuilder(
future: getLists(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
child: SpinKitDoubleBounce(color: Colors.green, size: 100),
);
} else {
// log(snapshot.data.toString());
var data = snapshot.data;
return Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.separated(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]),
onTap: () {
// code to pass a string value to tab 3 and navigate to tab 3
},
);
},
),
)
],
),
);
}
},
),
);
}
}
При нажатии на элемент списка на вкладке 1, как мне передать строку на вкладку 3 и одновременно перейти на вкладку 3?
Комментарии:
1. Пожалуйста, поделитесь кодом, в котором вы пытались решить эту проблему.
2. Существует много способов передачи значения от одного к другому, вы можете использовать конструктор, аргументы или статические переменные. пожалуйста, предоставьте более подробную информацию или код, чтобы мы могли выяснить вашу точную проблему.
3. Для тех, кто читает / использует этот код — обратите внимание, что объект TabController «controller» никогда не используется. Использование смешивается с DefaultTabController — так что следите за своим шагом 🙂
Ответ №1:
Вы можете скопировать вставить запустить полный код ниже
, который вы можете использовать https://pub.dev/packages/provider
Шаг 1: вы можете сохранить параметр в YourModel
Шаг 2: в Tab3
, вы можете получить доступ с помощью (context.watch<YourModel>().parameter)
фрагмент кода
class YourModel extends ChangeNotifier {
String _parameter = "";
String get parameter => _parameter;
void passParameter(String parameter) {
_parameter = parameter;
print(_parameter);
notifyListeners();
}
}
...
ChangeNotifierProvider(
create: (context) => YourModel(),
child: MyApp(),
),
...
class Tab3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("${(context.watch<YourModel>().parameter)}"));
}
}
...
return ListTile(
title: Text(data[index]),
onTap: () {
Provider.of<YourModel>(context, listen: false)
.passParameter(data[index]);
widget.controller.animateTo(2);
},
);
рабочая демонстрация
полный код
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'dart:collection';
import 'package:provider/provider.dart';
class YourModel extends ChangeNotifier {
String _parameter = "";
String get parameter => _parameter;
void passParameter(String parameter) {
_parameter = parameter;
print(_parameter);
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => YourModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(title: 'Flutter Demo Home Page'),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
TabController controller;
@override
void initState() {
super.initState();
controller = TabController(vsync: this, length: 3);
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {},
child: Scaffold(
appBar: AppBar(
title: Text("InstaPost"),
backgroundColor: Colors.black45,
bottom: TabBar(
controller: controller,
tabs: [
Tab(
text: "Tab 1",
),
Tab(text: "Tab 2"),
Tab(text: "Tab 3"),
// Tab(text: "My Posts")
],
),
),
body: TabBarView(
controller: controller,
children: <Widget>[
HashtagPage(controller),
Tab2(),
Tab3(),
],
),
),
);
}
}
class Tab2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text("Tab2");
}
}
class Tab3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(child: Text("${(context.watch<YourModel>().parameter)}"));
}
}
class HashtagPage extends StatefulWidget {
TabController controller;
HashtagPage(this.controller);
@override
_HashtagPageState createState() => _HashtagPageState();
}
class _HashtagPageState extends State<HashtagPage> {
Future<List<String>> _future;
Future<List<String>> getLists() async {
await Future.delayed(Duration(seconds: 1), () {});
return Future.value(["a", "b", "c", "d", "e", "f", "g"]);
}
@override
void initState() {
_future = getLists();
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {},
child: FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container(
child: SpinKitDoubleBounce(color: Colors.green, size: 100),
);
} else {
// log(snapshot.data.toString());
var data = snapshot.data;
return Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.separated(
separatorBuilder: (BuildContext context, int index) =>
Divider(),
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]),
onTap: () {
Provider.of<YourModel>(context, listen: false)
.passParameter(data[index]);
widget.controller.animateTo(2);
},
);
},
),
)
],
),
);
}
},
),
);
}
}
Ответ №2:
Это то, что сработало для меня.
Настройте TabController
как таковой:
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
tabs: ...,
),
),
body: TabBarView(
controller: _tabController,
children: ...
А затем переключаться между вкладками
// Set desired state to cause changes in target tab
setState(() {
appState.targetValue = newValue;
});
// Important for the timing/sequence of the actions
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_tabController.animateTo(newTabIndex);
});