Playing around with Flutter, I am trying to interact in one touch move with multiple elements. However my gesture is triggered only in first Container.
Is there any way to do this using GestureDetector or Listener classes?
I mean, is there any better solution than set Listener on parent element and calculate if current touch pointer position is between coordinates of child elements I want to recognize touch event?
Here is an example of code to illustrate the issue I am dealing with.
Swiping horizontaly, I would like to select all TapBox elements in Row.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Swipe select',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Swipe select'),
);
}
}
class TapBox extends StatefulWidget {
TapBox({Key key, this.bgColor}) : super(key: key);
Color bgColor;
#override
_TapBoxState createState() => new _TapBoxState();
}
class _TapBoxState extends State<TapBox> {
#override
Widget build(BuildContext context) {
return new Padding(
padding: new EdgeInsets.only(left: 10.0, right: 10.0),
child: new GestureDetector(
onPanUpdate: ((e) {
this.setState(() {
widget.bgColor = Colors.blueAccent;
});
}),
onPanStart: ((e) {
this.setState(() {
widget.bgColor = Colors.blueAccent;
});
}),
child: new Container(
width: 50.0,
height: 200.0,
color: widget.bgColor,
),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TapBox(bgColor: Colors.grey),
new TapBox(bgColor: Colors.grey),
new TapBox(bgColor: Colors.grey),
new TapBox(bgColor: Colors.grey),
new TapBox(bgColor: Colors.grey),
],
),
),
);
}
}
Related
I’m basically creating a slideshow that contains texts from a list resulting from an async function.
This is the class that contains the homepage, async function and slideshow :
class HomePage extends StatefulWidget {
HomePage({Key key, this.auth, this.userId, this.logoutCallback, this.profile})
: super(key: key);
final Auth auth;
final VoidCallback logoutCallback;
final String userId;
final ProfilePage profile;
#override
State<StatefulWidget> createState() => new _HomePageState();
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.auth, this.userId, this.logoutCallback, this.profile})
: super(key: key);
final Auth auth;
final VoidCallback logoutCallback;
final String userId;
final ProfilePage profile;
#override
State<StatefulWidget> createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
void initState() {
super.initState();
asyncMethod();
}
void asyncMethod() async {
await getMission1();
....
}
...
List<String> MissionData1 = [];
...
Future<void> getMission1() async{
DocumentSnapshot snap = await widget.auth.MissionRetriever1();
Map<String,dynamic> data = snap.data();
setState(() {
MissionData1.add(data['Q_Category']);
MissionData1.add(data['Q_Name']);
MissionData1.add(data['Q_Description']);
MissionData1.add(data['Q_Score']);
MissionData1.add(data['Q_Target']);
)};
...
Widget showTaskSlider() {
return new Column(
children:<Widget>[
CarouselSlider(options: CarouselOptions(height: 30.0.h, autoPlay: true, autoPlayInterval: Duration(seconds: 3), autoPlayAnimationDuration: Duration(milliseconds: 800), autoPlayCurve: Curves.fastOutSlowIn, aspectRatio: 2.0,
onPageChanged: (index, reason){setState(() {
_currentIndex= index;
});},
),
items: cardList.map((card){
return Builder(builder:(BuildContext context){
return Container(height: MediaQuery.of(context).size.height*0.30, width: MediaQuery.of(context).size.width,
child: Card(color:Colors.blueAccent, child: card,),
);
}
);
}).toList()
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(cardList, (index, url) {
return Container(
width: 3.0.w,
height: 5.0.h,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _currentIndex == index ? Colors.blueAccent : Colors.grey,
),
);
}),
),
],
);
}
}
and this is one of the classes of the slide
class Item1 extends StatelessWidget {
const Item1({Key key, this.homepage}) : super(key: key);
final _HomePageState homepage;
#override
Widget build(BuildContext context) {
return Container(
decoration: new BoxDecoration(image: DecorationImage(image: AssetImage("assets/illustrations/ill_1.jpeg"), fit: BoxFit.cover,),),
child: Column(
children: <Widget>[
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Row(children:[Image(image:AssetImage("assets/images/leaf.png"),width: 8.0.w,),Text(homepage.MissionData1 == null ? "Loading" : homepage.MissionData1[1], style:TextStyle(fontWeight: FontWeight.w500, fontFamily: 'Roboto',color: const Color(0xFFFFFFFF), fontSize: 15.0.sp),)]),Container(height: 20.0.h),Row(children: [Text("Dio Porco", style:TextStyle(fontWeight: FontWeight.w500, fontFamily: 'Roboto',color: const Color(0xFFFFFFFF), fontSize: 25.0.sp),)])],)), ]),
);
}
}
But when I start debugging it gives me this error
The following NoSuchMethodError was thrown building Item1(dirty):
The getter 'MissionData1' was called on null.
Receiver: null
Tried calling: MissionData1
I want to add some data from Stateful subclass to Stateless main
These are codes I wrote.
I know if I use Stateless widget only, these code will work properly.
But I want to some function that use Stateful widget later.
main.dart
children: [
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text(workout.title,
style: TextStyle(fontSize: 14)),
),
Padding(
padding: const EdgeInsets.only(top: 70),
child: Text(workout.count,
style: TextStyle(fontSize: 12)),
),
],
main_model.dart
Future add() async {
final collection = FirebaseFirestore.instance.collection('workoutlist');
await collection.add({
'title': newWorkoutText,
'count': int.parse(newWorkoutDigit),
'createdAt': Timestamp.now(),
});
add_page.dart
class AddPage extends StatefulWidget {
MainModel model;
final String newWorkoutText;
final String newWorkoutDigit;
AddPage({Key key,this.model,this.newWorkoutText, this.newWorkoutDigit}): super(key : key);
#override
_AddPage createState() => _AddPage();
}
class _AddPage extends State<AddPage> {
String newWorkoutText;
String newWorkoutDigit;
MainModel model;
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MainModel>.value(
value: model,
--------------------------------------------------------------------------
TextField(
keyboardType: TextInputType.number,
onChanged: (text) {
Text('{$widget.newWorkoutDigit}');
},
),
I am trying to create a vertical list view which contains horizontal list views using firebase as the datasource. I have created the horizontal scroll view which contains my occasions but now need to house that inside a vertical scroll view for different events.
Here is the code for my homepage
class HomePageTest extends StatefulWidget {
#override
_HomePageTestState createState() => _HomePageTestState();
}
class _HomePageTestState extends State<HomePageTest> {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
return StreamProvider<List<GreetingCard>>.value(
value: DatabaseService().cards,
child: Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(80),
child: MainAppBar(
text: 'Pick an occasion...',
),
),
body:
CardList(),
));
}
}
Card list:
class CardList extends StatefulWidget {
#override
_CardListState createState() => _CardListState();
}
class _CardListState extends State<CardList> {
#override
Widget build(BuildContext context) {
final greetingsCards = Provider.of<List<GreetingCard>>(context);
return Container(
height: 200.0,
child: ListView.builder(
itemCount: greetingsCards.length,
itemBuilder: (context, index){
return Column(
children: [
Text(greetingsCards[index].event),
Card(
child: CardTile(greetingCard: greetingsCards[index],)),
],
);
}, scrollDirection: Axis.horizontal),
);
}
}
and finally card tile:
class CardTile extends StatelessWidget {
final GreetingCard greetingCard;
const CardTile({Key key, this.greetingCard}) : super(key: key);
#override
Widget build(BuildContext context) {
return
Container(
height: 150.0,
width: 80.0,
child: Card(
child: ListTile(
onTap: () => print(greetingCard.ocassion.toString()),
title: Center(child: Text(greetingCard.ocassion)),
),
),
);
}
}
I'm thinking I should create another list view builder similar to the cards list but i'm curious to understand if there is a better way to do this.
Current output:
Desired output:
This is all you need!
Inside your vertical listView, you can have another listView having scroll direction set to horizontal,
scrollDirection: Axis.horizontal,
You can create a seperate method, so that you don't have to rewrite horizontal listView for every horizontal listView.
A newbie in flutter has a lot of stuff that is just starting to figure out now it's BLoC pattern and now I ran into a problem
I can not understand how to fix this error, seems to have written everything correctly
Here generic Interface for all BLoCs
abstract class BlocBase {
void dispose();
}
class BlocProvider<T extends BlocBase> extends StatefulWidget {
BlocProvider({
Key key,
#required this.child,
#required this.bloc,
}) : super(key: key);
final T bloc;
final Widget child;
#override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context) {
final type = _typeOf<BlocProvider<T>>();
BlocProvider<T> provider = context.ancestorWidgetOfExactType(type);
return provider.bloc;
}
static Type _typeOf<T>() => T;
}
class _BlocProviderState<T> extends State<BlocProvider<BlocBase>> {
#override
void dispose() {
widget.bloc.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return widget.child;
}
}
Here is the second file in which I use BLoC and where it gives an error
Here I use function validateAndCreateData through which I add Tickets
#override
Widget build(BuildContext context) {
final bloc = BlocProvider.of<TicketsBloc>(context);
return Scaffold(
drawer: MyDrawer(),
appBar: AppBar(
title: Text('Sports'),
backgroundColor: Colors.blueGrey[900],
// automaticallyImplyLeading: false,
actions: <Widget>[
IconButton(
icon: Icon(Icons.share),
tooltip: 'Share',
onPressed: () {
Navigator.of(context).pushNamed('/second_screen');
}),
IconButton(
icon: Icon(Icons.account_circle),
tooltip: 'Your account',
onPressed: () {
Navigator.of(context)
.pushReplacementNamed('/account_screen');
}),
IconButton(
icon: Icon(Icons.add),
tooltip: 'Add Tickets',
onPressed: () => validateAndCreateData(bloc),
)
]),
body: MyTab(),
);
}
void validateAndCreateData(TicketsBloc bloc) async {
bloc.createData(description, image, name, price);
}
Your error mean you don't have access to the bloc. You must wrap your app with the provider. If not you cannot inherited from this.
return BlocProvider(
child: MaterialApp(
title: 'My App',
home: HomeScreen(),
),
);
I have a demo app and the Internationalization is not working correctly.
My time code is +3 (North Cyprus). Language is TR. Date part works for TR.
but time is not working. Example instead of showing 08:27:18 it shows 05:27.18 GMT time.
More info: https://greenwichmeantime.com/time-zone/europe/turkey/
Examples: https://github.com/NTMS2017/Internationalization
Any help please?
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:intl/date_symbol_data_local.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Internationalization',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Internationalization'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DateFormat dateFormat;
DateFormat timeFormat;
#override
void initState() {
super.initState();
initializeDateFormatting();
dateFormat = new DateFormat.yMMMMd('tr_TR');
timeFormat = new DateFormat.Hms('tr_TR');
}
void _refresh() {
setState(() {});
}
#override
Widget build(BuildContext context) {
var dateTime = new DateTime.now();
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
backgroundColor: Colors.pinkAccent,
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(dateFormat.format(dateTime),
style: new TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
color: Colors.pinkAccent,
),
),
new Text(timeFormat.format(dateTime),
style: new TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold
),
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _refresh,
tooltip: 'Refresh',
child: new Icon(Icons.refresh),
),
);
}
}
With #GünterZöchbauer help. I check my android simulator.
My Simulator is Nexus 5X API 26.
Setting the simulator Language to TR and Region to Turkey the above code works well.