Way to efficiently create multiple same widgets with different text - flutter

We are trying to create a language learning app as a project in flutter.
One level would have same widget tree just repeated multiple times with different questions and answers to be chosen.
Once correct answer is chosen it takes you to new question.
Any ideas on how we can efficiently create multiple of same widgets with different text inside?

You can extract your widget as Widget with text parameter. So just use the widget anywhere and pass text argument now you will get same widget with different text.

Generally speaking, if you want to create multiple objects/widgets from the same class with slight changes, all you need to do is to create a constructor and pass some data to it.
Here's an example:
Class MyText extends StatelessWidget {
final String text;
MyText({this.text});
// your build method that returns the text goes here..
}
To use:
MyText('Hello');
MyText('World');
Good luck building your game!

Related

Riverpod Flutter: Multiple providers for one screen

I'm new to riverpod, and I want to check that I am doing things correct.
I have a screen on my Flutter app where the use inputs lots of information about a session. Like start time, end time, notes, duration, date etc etc. All this data in the end is stored in a dart complex object MySession(), will all the above properties.
My question is, in the meantime, I am creating a seerate provider for each field. Like this:
final selectedDateProvider = StateProvider((ref) => DateTime.now());
final sessionDurationMinutesProvider = StateProvider<int>((ref) => 0);
Now in the class, I call the providers like this in the build method:
selectedDate = ref.watch(selectedDateProvider);
sessionDurationMinutes = ref.watch(sessionDurationMinutesProvider);
Then I display them in the widgets.
When they are editing, I save the state like this:
ref.read(selectedDateProvider.notifier).state = datePick;
My question is, I have lots and lots of fields on this page. So I have to create lots of providers for each field. Is this the correct practise? Can I not make a customclass for all these fields, and then make one provider which will return this custom class?
On the riverpod docs it says: You should not use StateProvider if: your state is a complex object (such as a custom class, a list/map, ...)
https://riverpod.dev/docs/providers/state_provider
I hope its clear!
Thanks
You already answered your question ;)
Yes, you can.
Make a class that will store the state of all the input fields and expose it through StateProvider.
To do it effectively you will probably need a copyWith method which can be written manually or generated. One of the possible approaches is to use freezed.

Does anyone know if it is possible to extend a flutter widget?

Is it possible to extend a widget? take for instance the CalendarDatePicker widget. I like the existing features but I want to be able to extend it.
I want to be able to have a little dot under each day that has some events whether it is just one or multiple events. If a day doesn't have any events, then nothing needs to show under that day. Events would be coming from a firebase Firestore.
The reasons are:
I like the CalendarDatePicker and I prefer not having to install a new package. I see people are using Table_Calendar. It is nice but I am trying to reuse leverage what is already there and stay away from installing too many packages.
I'd prefer not to design one from scratch when there is one that already does 98% of what needs to get done.
Thanks
You can extend widgets and override its properties and methods with extends keyword (see docs). It is simple OOP inheritance. But anyway you should fully override build method to complement existing UI. Do it, copy existing code from CalendarDatePicker build method to you custom class build method and update this code as you wish:
class CustomDatePicker extends CalendarDatePicker {
const CustomDatePicker({
Key? key,
// here you can use constructor properties that you need
// and pass them to superclass constructor
}) : super(...);
#override
Widget build(BuildContext context) {
// use code from CalendarDatePicker build method
// and update it as you wish
}
}

Name conflicts with custom widgets in Flutter

What is the best way to make custom widgets in Flutter that don't conflict with those exported by the material package? Specifically: I'm trying to make a design system based on atomic design. So, let's say I want my own Text and Card widgets. I can't name them Text or Card because both of these are exported by the material package.
Some options that I've considered:
Creating a ui library and importing using as
// components/atoms/Text.dart
import "package:flutter/material.dart" hide Text;
import "package:flutter/material.dart" as material show Text;
class Text extends StatelessWidget {
Text(String content);
Widget build(BuildContext context) {
// Imagine some more complicated styling specific to my design system
return material.Text(content);
}
}
// components/ui.dart
library ui
export "package:my_app/components/atoms/Text";
// screens/HomeScreen.dart
import "package:flutter/material.dart";
import "package:my_app/components/ui" as ui;
class HomeScreen extends StatelessWidget {
Widget build(BuildContext context) {
// Example usage
return ui.Text(content);
}
}
This doesn't feel great... First, I need to remember to include as whenever I import the ui library, and second, it's slightly annoying to have to hide and show classes in my Text implementation.
Just hide the conflicting classes
// screens/HomeScreen.dart
import "package:flutter/material.dart" hide Text;
import "package:my_app/components/Text";
class HomeScreen extends StatelessWidget {
Widget build(BuildContext context) {
// Example usage
return Text(content);
}
}
Similar to option (1), I don't want to have to remember to hide all the classes that conflict with my custom widgets.
Just use different names
Maybe AppText or ThemeText or UIText or AtomText? This doesn't feel great either, especially for some of the other widgets like IconButton.
Is there a convention around this, or some decent solution? I haven't seen any custom UI libraries, but this is mostly useful for teams that want to reuse widgets across apps and keep a consistent style.
From what I gather, you want your custom Text class to do the exact same thing as a normal Text widget, but with a different design. If that really is the case, I propose that you change the ThemeData of your project. The MaterialApp widget takes a theme argument, so you can style your TextTheme, CardTheme, IconButtonTheme etc. in there. This would prevent any naming conflicts, save you a lot of coding, and makes it easy to tweak.
Things such as TextTheme allow for different types of styles, such as headlines, bodytext, etc., as described here.
You can add 'My' at the beginning of the widget, for example, 'MyText' instead of 'Text' and 'MyCard' instead of 'Card'.
You can use a tricky way, in my case I use an intentionally wrong dictation for naming. For instance, instead of 'Card' you can name 'Cart', or instead of 'Text', you can name tekst.

Treat different widgets as the same so not to rebuild the element tree

Here is my dart pad example of my problem: https://dartpad.dev/46edc2b00fe11eac17c8a0a7dfa19e15
I have created some encapsulate widgets, Counter1 and Counter2. They both have the same widget tree structure with only the leaves changing. When I replace Counter1 with Counter2 it rebuilds all the elements rather than just update them.
Is there a way to tell Flutter, these widgets are really the same thing and you don't need to create a new Element just update your reference?
It seems inefficient to recreate the elements when only the top encapsulating widget is changing.
Update: The general direction I am thinking of accomplishing this is by create a class that extends StatelessWidget and then does something to say they're the same thing.

How do I add ScrolledWindow support to a custom Widget in GtkMM?

I am writing a custom widget for Gtkmm that is supposed to display a huge dataset (imagine something like a 4096x256 character datasheet).
Mostly for reasons of elegance, but also for a possible usage in a Glade/Gtk-Builder editor, I want this widget to support ScrolledWindow natively, that is, once it is set as the child of ScrolledWindow, it is recognized as a scrollable widget, allowing to set horizontal and vertical Adjustment objects on it, which it can subsequently tamper with.
It appears to do so, I need to do something like this in the constructor of my widget:
// get Gtk C type from wrapper class
GtkWidget* gwidget = this->gobj();
// imagine code here that magically creates a gobject signal,
// that we can catch in C++.
// this is actually the part which I don't know how to do.
guint my_signal = magic_way_to_create_this_signal(
&MyClass::rainbow_unicorn_signal_handler);
// make ScrolledWindow recognize this window as scrollable
GTK_WIDGET_GET_CLASS(gwidget)->set_scroll_adjustments_signal = my_signal;
Later on, the signal emitted by ScrolledWindow when the widget is added needs to be caught by my Widget through a signal proxy method or something? I have no idea.
How can I do this?
The 'magic_way_to_create_this_signal' is g_signal_new(). You call it in your widget's my_widget_class_init() function which is part of the GObject way of defining a class. I'm not exactly sure what the equivalent is in Gtkmm.
See also the footnote in the GTK docs, where it is explained why making a widget natively scrollable is such a hassle.
You could also put your widget into a Gtk::Viewport which adds scrolling capabilities to its child widget.