I'm making a bottom menu. I want make 3 screens. and for this i want make 3 single classes. 1 the screen - 1 a class. And for this all using 1 the Scaffold. How can i do it? All my classes must be a StateFull for using function "setState"
I was found in google source codes. but they for single widget
import 'package:flutter/material.dart';
import 'package:async/async.dart';
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 1;
final _widgetOptions = [
Text('Index 0: Home'),
Text('Index 1: Business'),
Text('Index 2: School'),
];
#override
Widget build(BuildContext context) {
//API_Tumbler api = new API_Tumbler("3EuKq8hIimaGFxY3wqzL7MXw5qZuN3Zcx9cIEgWKT4UTINwGec", "gjkCRximp0OJtFGN4Zd8xD2yPMwjw557EtgVvKhmqLNdI9IOBx");
return Scaffold(
appBar: AppBar(
title: Text("Miner of Memes"),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: [
new BottomNavigationBarItem(
icon: Icon(Icons.library_books),
title: Text('Блоги'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.subject),
title: Text('Лента'),
),
new BottomNavigationBarItem(
icon: Icon(Icons.send),
title: Text('Отправка')
)
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
);
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
}
This is can be done by replacing the Text widget with the classname in
_widgetOptions.
Make a file lets say firstScreen.dart with the following code :
class Firstscreen extends StatefulWidget {
const FirstScreen({ Key key }) : super(key: key);
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
#override
Widget build(BuildContext context) {
return Text("This is FirstScreen);
}
}
now in your code edit this.
import './firstScreen.dart' //include the file created
...
final _widgetOptions = [
FirstScreen(),
Text('Index 1: Business'),
Text('Index 2: School'),
];
Just do same for other screens too.
Hope it helps you :)
Related
I want to be able to use the mouse to drag / swipe the screen instead of using the scroll wheel. I'm running on Pop! OS 22.04 (Ubuntu Linux). Any help appreciated :)
Just add the snippet below to enable mouse dragging scroll and create it in the MaterialApp.scrollBehavior property:
// Enable scrolling with mouse dragging
class MyCustomScrollBehavior extends MaterialScrollBehavior {
#override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
Check the live demo on DartPad and below the source code as a minimal-reproducible-example
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
//
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
scrollBehavior: MyCustomScrollBehavior(), // <- Here
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
//
return Scaffold(
body: Center(
child: ListView.separated(
itemBuilder: ((context, index) =>
ListTile(title: Text('Item $index'))),
separatorBuilder: (context, index) => const Divider(),
itemCount: 100,
),
),
);
}
}
// Enable scrolling with mouse dragging
class MyCustomScrollBehavior extends MaterialScrollBehavior {
#override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
import 'package:flutter/material.dart';
import 'package:onetarget/screens/background_painter.dart';
class AuthScreen extends StatefulWidget {
const AuthScreen({Key? key}) : super(key: key);
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen>
with SingleTickerProviderStateMixin {
AnimationController _controller; ----ERRRRROR[enter image description here][1]
#override
void initState() {
// TODO: implement initState
_controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
SizedBox.expand(
child: CustomPaint(
painter: BackgroundPainter(),
))
],
),
);
}
}
I want to build a sign in page but it doesn't work. I did everything and copy paste it from the original video: https://youtu.be/bpvpbQF-2Js
enter link description here
GitHub:enter link description here
Just mark it late.
late AnimationController _controller;
I am new at Flutter and I can't understand some things. I split small widgets for improving my system but i dont know how i will add data from other page.I want to show days of week and i splitted this days another widget this way "DaysOfWeek.dart" and i wrote class name this widget in main.dart file but i have an implement error. how can i fix ?
main.dart
import 'package:calendar_app/dayofweeks.dart';
import 'package:flutter/material.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Calendar',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
var calculateDays;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child:Column ( children: <Widget>[
Row(
DaysOfWeek(),), // here is the my small widget
],
),
),);
}
}
dayofweeks.dart :
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class DaysOfWeek extends StatelessWidget{
#override
Widget build(BuildContext context) {
List<DateTime> calculateDays(DateTime startDate, DateTime endDate) {
List<DateTime> days = [];
for (int i = 0; i <= endDate.difference(startDate).inDays; i++) {
days.add(startDate.add(Duration(days: i)));
}
return days;
}
// TODO: implement build
throw UnimplementedError();
}
}
I hope this will help:
main.dart:
import 'dayofweeks.dart'; //1st
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
title: 'Flutter Calendar',
home: Scaffold(
body: MyHomePage(),
),
));
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(children: <Widget>[
(Row(
children: <Widget>[DaysOfWeek()],
))
])),
);
}
}
dayofweeks.dart:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class DaysOfWeek extends StatelessWidget{
#override
Widget build(BuildContext context) {
List<DateTime> calculateDays(DateTime startDate, DateTime endDate) { //Sorry I don't understand the calculateDays() function
List<DateTime> days = [];
for (int i = 0; i <= endDate.difference(startDate).inDays; i++) {
days.add(startDate.add(Duration(days: i)));
}
return days;
}
throw UnimplementedError();
}
}
and also if you found a problem in widget_test.dart,
replace this line
await tester.pumpWidget(MyApp());
with this one
await tester.pumpWidget(MaterialApp());
I have a PageView inside LayoutBuilder to get the widget size.
Since it depends on the widget size, I don't know how many pages there will be until the widget is built. So I added FutureBuilder inside LayoutBuilder, so the number of pages can be calculated asynchronously. Here's my code but it's waiting indefinitely in ConnectionState.waiting.
What's the problem in the code and how to solve it?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(home: ScrollableTabsDemo());
}
}
class _Page {
const _Page({this.icon, this.text});
final IconData icon;
final String text;
}
const List<_Page> _allPages = <_Page>[
_Page(text: 'tab 1'),
_Page(text: 'tab 2'),
_Page(text: 'tab 3'),
];
class ScrollableTabsDemo extends StatefulWidget {
static const String routeName = '/material/scrollable-tabs';
#override
ScrollableTabsDemoState createState() => ScrollableTabsDemoState();
}
class ScrollableTabsDemoState extends State<ScrollableTabsDemo>
with SingleTickerProviderStateMixin {
TabController _controller;
#override
void initState() {
super.initState();
_controller = TabController(vsync: this, length: _allPages.length);
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
final Color iconColor = Theme.of(context).accentColor;
return Scaffold(
appBar: AppBar(
title: const Text('Scrollable tabs'),
bottom: TabBar(
controller: _controller,
isScrollable: true,
tabs: _allPages.map<Tab>((_Page page) {
return Tab(text: page.text);
}).toList(),
),
),
body: TabBarView(
controller: _controller,
children: _allPages.map<Widget>((_Page page) {
return SafeArea(
top: false,
bottom: false,
child: LayoutBuilder(builder: (context, constraints) {
return FutureBuilder<int>(
future: getPageCount(),
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
print("none ${snapshot.data}");
return Text('none');
case ConnectionState.active:
print("active ${snapshot.data}");
return Text('active');
case ConnectionState.waiting:
print("waiting ${snapshot.data}");
return Center(child: CircularProgressIndicator());
case ConnectionState.done:
print("done ${snapshot.data}");
return buildPageView(snapshot.data);
}
});
}),
);
}).toList(),
),
);
}
Future<int> getPageCount() => Future.delayed(Duration(seconds: 3), () => 5);
Widget buildPageView(int pageCount) {
return PageView.builder(
itemBuilder: (context, position) {
return Container(child: Center(child: Text(position.toString())));
},
itemCount: pageCount,
);
}
}
The documentation for FutureBuilder states that you should not create the future on every build: https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html
Either run getPageCount in initState, in a field initializer, or prepare a stateful widget similiar to FutureBuilder that takes a future creating function and calls this function in it's own initState.
EDIT:
With this helper you can have the future cached automatically
class CachingFutureBuilder<T> extends StatefulWidget {
final Future<T> Function() futureFactory;
final AsyncWidgetBuilder<T> builder;
const CachingFutureBuilder(
{Key key, #required this.futureFactory, #required this.builder})
: super(key: key);
#override
_CachingFutureBuilderState createState() => _CachingFutureBuilderState<T>();
}
class _CachingFutureBuilderState<T> extends State<CachingFutureBuilder<T>> {
Future<T> _future;
#override
void initState() {
_future = widget.futureFactory();
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: _future,
builder: widget.builder,
);
}
}
If your getPageCount requires size as input, you could use that helper widget like in the code below. The trick is to use ValueKey so that Flutter knows to reinit the CachingFutureBuilder. Make sure you don't have any size changing animations because it would cause the Future to reload on every frame.
class ScrollableTabsDemo extends StatelessWidget {
Future<int> getPageCount(Size size) {
return Future.value(1);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: LayoutBuilder(
builder: (context, constraints) {
final size = Size(constraints.maxHeight, constraints.maxWidth);
return CachingFutureBuilder<int>(
key: ValueKey(size),
futureFactory: () => getPageCount(size),
builder: (context, snapshot) {
return Text(snapshot.toString());
},
);
},
),
),
);
}
}
You should not use the FutureBuilder inside a LayoutBuilder. The builder might be called several times and therefore the future gets called every single time. The builder in the LayoutBuilder, gets called when the UI its updated. For example, if you change from portrait to landscape, the builder it's called twice, so the future too.
In current implementation of SearchDelegate, there is no option to change the hint text. When the query is empty, search screen is displaying "Search" in the query field as a hint text.
Hint text is currently defined on line 395 as follows:
final String searchFieldLabel = MaterialLocalizations.of(context).searchFieldLabel;
There is, however, an existing issue to this subject reported.
I wasn't able to come up with any solution for this.
Do you know any workaround for the issue?
Currently SearchDelegate has an optional member "searchFieldLabel" to specify the label of the search field.
It should look something like this:
#override
String get searchFieldLabel => 'custom label';
class SongSearch extends SearchDelegate<String> {
SongSearch({
String hintText = "Song Search",
}) : super(
searchFieldLabel: hintText,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.search,
);
.....
There is a workaround for this by creating your own DefaultMaterialLocalizations class and passing it into the MaterialApp widget:
void main() => runApp(SearchApp());
class SearchApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: [
CustomLocalizationDelegate(),
],
home: Scaffold(
appBar: AppBar(
title: Text('Search demo'),
),
body: Center(
child: Builder(
builder: (context) => MaterialButton(
child: Text('Search'),
onPressed: () => showSearch(
context: context,
delegate: DummyDelegate(),
),
),
),
),
),
);
}
}
class DummyDelegate extends SearchDelegate<String> {
#override
List<Widget> buildActions(BuildContext context) => [];
#override
Widget buildLeading(BuildContext context) => IconButton(
icon: Icon(Icons.close),
onPressed: () => Navigator.of(context).pop(),
);
#override
Widget buildResults(BuildContext context) => Text('Result');
#override
Widget buildSuggestions(BuildContext context) => Text('Suggestion');
}
class CustomLocalizationDelegate extends LocalizationsDelegate<MaterialLocalizations> {
const CustomLocalizationDelegate();
#override
bool isSupported(Locale locale) => locale.languageCode == 'en';
#override
Future<MaterialLocalizations> load(Locale locale) => SynchronousFuture<MaterialLocalizations>(const CustomLocalization());
#override
bool shouldReload(CustomLocalizationDelegate old) => false;
#override
String toString() => 'CustomLocalization.delegate(en_US)';
}
class CustomLocalization extends DefaultMaterialLocalizations {
const CustomLocalization();
#override
String get searchFieldLabel => "My hint text";
}
As far as the hint color is concerned, if you're still looking for a solution, HintColor won't work. Use the InputDecoration property of ThemeData like so:
inputDecorationTheme: InputDecorationTheme(hintStyle: Theme.of(context).textTheme.title.copyWith(color: Colors.white),)
With null-safety, you should do something like:
class MyDelegate extends SearchDelegate<String> {
final String? hintText;
MyDelegate({this.hintText});
#override
String? get searchFieldLabel => hintText;
// Other overrides...
}
Usage:
showSearch<String>(
context: context,
delegate: MyDelegate(hintText: 'My hint'),
);
You can just extend the source class and override its default field in your constructor to define your own value for the field?
For example:
class CustomSearch extends SearchDelegate<String> {
CustomSearch() : super(searchFieldLabel: "My own hint");
}
Use the "searchFieldLabel" properties to customize the placeholder for the search box and can also modify the SearchDelegate properties listed below:
SearchDelegate({
this.searchFieldLabel,
this.searchFieldStyle,
this.searchFieldDecorationTheme,
this.keyboardType,
this.textInputAction = TextInputAction.search,
})........
To illustrate:
class SearchScreen extends SearchDelegate {
SearchScreen({
String hintText = "অনুসন্ধান",
}) : super(
searchFieldLabel: hintText,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.search,
searchFieldStyle: TextStyle(
color: Color.fromARGB(178, 255, 255, 255),
fontWeight: FontWeight.bold),
);
.
.
}