All posts by admin

Flutter Staggered Animations

ref – https://pub.dev/packages/flutter_staggered_animations/

result (.mov)

In your pubspec.yaml file, include

We use AnimationConfiguration.toStaggeredList with a duration of Duration(milliseconds: 1375).

We then fill in the childAnimationBuilder, which is the specified way on how to animate each widget in the List. The idea here is that we wrap this widget with FadeInAnimation and SlideAnimation. It’s a combination effect.

Hence, what we’ve stated in childAnimationBuilder is that for each child widget, we want to apply the slide and fade in animation to each widget.

This is for fade in on lists.

Full Code

Fade and Slide transition in Flutter

ref – https://www.youtube.com/watch?v=xIX9Bo_yjvo
https://medium.com/codechai/flutter-animation-basics-explained-with-stacked-cards-9d34108403b8

First we have to refactor our class into a StatefulWidget.

1) extends StatefulWidget
2) @override createState()
3) extends State
4) with SingleTickerProviderStateMixin

When you add your SingleTickerProviderStateMixin, it tells Flutter that there is some animation in this widget and this widget needs to notified about the animation frames of flutter.

Animation controller is one of the basic things necessary for creating magic in flutter. You can imagine this as the dictator of the animation on screen. It contains the duration of the animation and so it will split out values between 0 to 1 based on the duration and the ticker value.
Controller value is 0 -> Start of your animation
Controller value is 1 -> End of your animation

vsync property is related to the Ticker and if the stateful widget has the Mixin, you can pass this to this property.
Animation with just the controller is possible when your animated value is also from just 0 to 1. You can pass the controller value to the widget and start the animation by calling controller.forward()

Tween

Short for in-betweening, the process of generating intermediate frames between two images to give the appearance that the first image evolves smoothly into the second image.

Creating the in-between values is the responsibility of Tween. Tween takes a begin ,end, properties and to create a Animation variable we should use the animate method and pass the controller.

When you call animation.forward() it will produce a smooth animation from the begin Offset value to end Offset value.

Fading in a Text

Wrap some padding around it using a Container

Now let’s start a fade transition. We pass in our animation Controller for the opacity. Our animation controller has an animation time of 1500 milliseconds. Thus, it will animate the opacity from -1 to 0 in 1500 milliseconds.

Run the project and you’ll the text have this fade effect.

Transition the Text

Let’s remove the fade transition from our Text Container. Our Text container should simply be:

We wrap a SlideTransition like so:

child class

So in order to make this work, we have a child class and that houses Text and an Image.

As you can see, it references an injected animation controller. The animation controller in the parent class holds state:

SlideTransition – for position property we assign it a Tween. The tween takes the animationController in order to animate.

FadeTransition – for opacity, we stick in the animation controller, which says duration should be 1.5 seconds.
However, we decide to forgo this feature and just use transition.

In the parent class, we use it like so:

Now when the animation starts, the text will transition from the left and come in towards the right.

Moving the button up

So now using the same tactic, we create another class called Bottom, that will reference the parent class animationController. It will have some static UI widgets which we will animate.

For its build function, we return a slide Transition.

The position needs a Tween. We want it to come from bottom off screen

So we know that it will slide something from offscreen (x is 0, y is 1) up to original position.
That something is a container that holds text:

hm 3 references

1) Fetching Random Name from API using Dio and Bloc

https://blog.usejournal.com/flutter-http-requests-with-dio-rxdart-and-bloc-da325ca5fe33
original source – https://github.com/jhomlala/randomuser

Updated source

2) Carousel

ref – https://pub.dev/packages/carousel_slider

First, we have an array of image URLs where images are located.

code for imgList

We take that array and for each item, we create a Container, with another Container as the child.

The child Container has a ClipRRect, which has a Stack.

This Stack means it contains an Image, with a Positioned Widget.
The Positioned widget has a Container and fits text inside of some padding.

Thus, this completes our List of Widgets.

The code for imageSliders

We then stick this list of Widgets to the items property of CarouselSlider.

code for CarouselSlider

Then in your class, you use it like so:

VerticalSliderDemo class

3) Navigating from one page to another

ref – https://flutter.dev/docs/cookbook/navigation/navigation-basics

const constructors

ref – https://stackoverflow.com/questions/21744677/how-does-the-const-constructor-actually-work

Const constructor creates a “canonicalized” instance.

That is, all constant expressions begin canonicalized, and later these “canonicalized” symbols are used to recognize equivalence of these constants.

Canonicalization:

A process for converting data that has more than one possible representation into a “standard” canonical representation. This can be done to compare different representations for equivalence, to count the number of distinct data structures, to improve the efficiency of various algorithms by eliminating repeated calculations, or to make it possible to impose a meaningful sorting order.

This means that const expressions like const Foo(1, 1) can represent any usable form that is useful for comparison in virtual machine.

The VM only needs to take into account the value type and arguments in the order in which they occur in this const expression. And, of course, they are reduced for optimization.

Constants with the same canonicalized values:

Constants with different canonicalized values (because signatures differ):

Constants are not recreated each time. They are canonicalized at compile time and stored in special lookup tables (where they are hashed by their canonical signatures) from which they are later reused.

P.S.

The form #Foo#int#1#int#1 used in these samples is only used for comparison purposes and it is not a real form of canonicalization (representation) in Dart VM;

But the real canonicalization form must be “standard” canonical representation.

final vs const

ref – https://stackoverflow.com/questions/50431055/what-is-the-difference-between-the-const-and-final-keywords-in-dart

Cubit and Bloc simple example

ref –

  • https://resocoder.com/2020/08/04/flutter-bloc-cubit-tutorial/
  • https://medium.com/flutterando/cubit-a-simple-solution-for-app-state-management-in-flutter-66ab5279ef73
  • http://chineseruleof8.com/code/index.php/2021/04/14/beginning-bloc-for-flutter/
  • http://chineseruleof8.com/code/index.php/2021/04/15/working-with-flutter-bloc/
  • https://github.com/irvine5k/cubit_movies_app/

A Cubit is the base for Bloc (in other words Bloc extends Cubit).

Cubit is a special type of Stream which can be extended to manage any type of state .

A functions is generally that something you create to do some orders as you want and this function will be achieved my orders when I would CALLING IT so it can’t achieve anything without any call from me . something like when I call KFC to order some food the function here is calling the restaurant to order my food because the restaurant can’t order food to me without calling it.

It replaces events in the bloc architecture. Originally, UI actions create events. Events get mapped to State. And we return certain state to update the data to be drawn in the UI.

However, instead of mutating individual fields, we emit whole new MyState objects. Also, the state is in a class separate from the one responsible for changing the state.

Importing Cubic

pubspec.yaml

State

A rule of thumb is to always build out the state class(es) first. So, what kind of WeatherState do we want to have?

We have the abstract class WeatherState to denote top of hierarchy.

We then create different Weather States that implements this abstraction. In our case:

WeatherInitial – This WeatherInitial state will indicate that no action has yet been taken by the user and that we should display an initial UI
WeatherLoading – we are waiting for the weather to arrive from its web api
WeatherLoaded – the data has arrived!
WeatherError – internet connection broke somehow.

We also override annotation operator ==. This is because UI updates when state are different. Flutter will do a comparison between different states. If the states are different, update the UI. If they are the same, don’t do anything. Thus, for our Weather state, we need to override this to let flutter do the comparison.

If the two states are identical, then UI won’t do anything.
If the incoming object is of the same state (say WeatherLoaded) and the state’s weather object is the same, then we return true and UI won’t update.

But if either:
– the Object o is of another state
– the weather has changed

then we return false, to let Flutter know that the state have changed.

Always override equality of the state classes. Bloc will not emit two states which are equal after one another.

Thus, if we do not override equality, Bloc will ALWAYS update the UI and it degrades performance.

Cubit

Having finished our work on the state, let’s implement the WeatherCubit that will perform logic such as getting the weather from the WeatherRepository and emit states.

So we extend from Cubit

We ctrl + click Cubit to see what’s going on underneath. We see that it’s an abstract class that uses a StreamController. This is mentioned in our earlier tutorials on basic blocs and stream:

  • http://chineseruleof8.com/code/index.php/2021/04/14/beginning-bloc-for-flutter/
  • http://chineseruleof8.com/code/index.php/2021/04/15/working-with-flutter-bloc/

A stream can only take one type, and we see that Cubit takes on the state that we specify in the type bracket.
The StreamController instance then broadcasts it and it will be sink.add, or stream.listen accordingly. But when using Cubic, all that details are hidden away.

Do take note of the constructor. It takes a state as parameter.

Hence that is why in our initialization code, we put WeatherInitial() instance because it assigns the initial state to Cubit.

We then have our a weatherRepository instance that gets the data from a web api.

Notice that we don’t need to override mapEventToState here like we do in bloc architecture.
That is because in Cubit, there is no events. We only have functions that trigger state change.

Hence, in our case, we call getWeather to asynchronously get data. But before it does, we first emit a WeatherLoading state instance. This state is to trigger a circular indicator in our UI, as will be shown later.

Then we do the async operation and get the weather data. After receiving this data, we emit that state to be loaded, along with the weather data itself.

The states then get reflected on the UI through BlocBuilder:

weather_search_page.dart

Running the App

In the very beginning, we have this:

It’s a class that extends StatefulWidget. We need to override StatefulWidget’s abstract method createState. createState returns State. Thus, we need to create a class that extends from State. We name it WeatherSearchPageState. The type of State is WeatherSearchPage.

We then override the build function, which is used to build the UI.

When we run the app, we get the log messages like so:


flutter: weather_search_page.dart – WeatherSearchPage – createState
flutter: weather_search_page.dart – state: Instance of ‘WeatherInitial’
flutter: weather_search_page.dart – WeatherInitial state –> returning buildInitialInput() UI

We get WeatherInitial state because in WeatherCubit, we initialized state it WeatherInitial():

The way how the UI is implemented is. Our UI is organized in such a way that whenever a state is such, we return the proper UI widgets.

Then when we put in a city for weather, we start at the cubit. It uses the weather repo to do its async operation. Once its done, it emits a state. This state then is caught in the UI where weather_search_page.ldart sees that its a WeatherLoading.


flutter: weather_cubit.dart – weather is loading…
flutter: weather_repository.dart – getting weather for shanghai
flutter: weather_search_page.dart – state: Instance of ‘WeatherLoading’
flutter: weather_search_page.dart – WeatherLoading state –> returning buildLoading() UI

Then few seconds later, in weather_cubit, we receive weather data. It will emit WeatherLoaded.
Now, Cubit will do a comparison between WeatherLoading and WeatherLoaded in its operator overloaded ==.


flutter: weather_cubit.dart – received weather data!
flutter: weather_state.dart – WeatherLoaded – comparing Instance of ‘WeatherLoading’ and Instance of ‘WeatherLoaded’
flutter: weather_state.dart – DIFFERENT state, update UI NOW!

When the states are different, we update UI.


flutter: weather_search_page.dart – state: Instance of ‘WeatherLoaded’
flutter: weather_search_page.dart – WeatherLoaded state –> returning buildColumnWithData() UI

Working with Flutter Bloc

ref – https://pub.dev/packages/flutter_bloc

Events

Events are triggered due to some user action from the UI layer. Events can be represented via hierarchy by using abstract classes.

For example, in the app we are going to build today, there are three events, FetchWeatherEvent, ResetWeatherEvent, RefreshWeatherEvent. They all extend from WeatherEvents.

They are triggered in WeatherView. In our UI, say we have a handler called onRefresh. When the refresh button is clicked, it will execute it like so:

Notice that it uses BlocProvider to add our Event to the event stream’s sink. This is essentially what’s happening when we call BlockProvider.of(context).add(…).

RefreshWeather extends from WeatherEvents, as are other classes.
Thus, on the UI layer, we put events on the event stream in such ways.
When the event arrives on the event stream, we have BlocObserver.

The idea is that we pass the Bloc and Event into our BlocObserver.
BlocObserver will then call weatherBloc’s mapEventToState with this particular event.

mapEventToState is an abstract function in our weatherBloc, which yield states to this particular event. Yielding state means we are sending the state in the counter stream back to the UI layer.

Notice that we await a weather repo to get the weather from a web API. Then we have received it, we just yield the state class WeatherLoaded with the weather data. Of course we can yield instances of other state classes that implements the State abstract class, which is used to put up say an indicator or stop an indicator.

weatherState.dart

Notice WeatherLoaded has a weather property that holds on to this new data.
We also override props because our abstract class WeatherStates extends Equatable.
In order to see if this instance is equal to another, we need to put our weather object in the props array
so Equatable can do the comparison

Okay, so now from the WeatherBloc, we have yielded the WeatherLoaded instance along with the weather data, now what?

We come back to simpleBlocObserver and hit the onTransition.

SimpleBlocObserver.dart

So this means that we’re currently on the WeatherEmpty state
The event passed in is fetchWeather
Because Event FetchWeather, weatherBloc yields WeatherLoading…that is why our nextState is WeatherLoading.

When the data arrives the state will be WeatherLoaded. But first! Let’s see what happens to the UI when we our state is on WeatherLoading.

In our weather.dart, our BlocConsumer’s listener will be activated.

BlocConsumer

BlocConsumer exposes a builder and listener in order react to new states.

BlocConsumer is analogous to a nested BlocListener and BlocBuilder but reduces the amount of boilerplate needed.

BlocConsumer should only be used when it is necessary to both rebuild UI and execute other reactions to state changes in the bloc.

BlocConsumer takes a required BlocWidgetBuilder and BlocWidgetListener and an optional bloc, BlocBuilderCondition, and BlocListenerCondition.

If the bloc parameter is omitted, BlocConsumer will automatically perform a lookup using BlocProvider and the current BuildContext.

in our case, look aa builder property. In it, its if-else has a condition where if state is WeatherLoading, then it returns an instance of a Center Widget. In it, it has a CircularProgressIndicator which will then run on the UI.

weather.dart

So now our circular indicator is running, we’re also fetching data from the web api.

weatherBloc.dart

Once the data comes back, we yield WeatherLoaded with the data. The BlocConsumer’s state changed to WeatherLoaded and it simply updates the UI.

In our particular case, we update our refresh control, and give it a ListView where it calls DisplayWeather to put all the text and new data onto the screen.

BottomNavigationBar flutter

ref – https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html

Flutter Food Delivery App – part 3 (Recent Orders)

Recent Orders

Put recent orders as the next item in the widget array.

home_screen.dart

Create our basic RecentOrders class by typing: stl + tab. Then enter RecentOrders for the class name.

We then return an instance of a column.
We create an array of widgets and assign it to the children property.
Our first widget will be Text, which says Recent order. We give it some Text styling.

Creating list and filling it with the user’s food data

We then want to create a ListView and fill it with some basic text. Like so:

Making it horizontal and having clipped Rounded Corner Images

Putting text in and spacing them correctly

Putting in the Add button

Push Our button to the right

Now in order to push the add button all the way to the right side, we need to wrap:
1) our image
2) our column of texts

in a row widget.

Then, we can use the property of our main axis alignment for our larger row container.

Text Overflow

Wrap our Texts Container, and outer Row Container in a widget called Expanded

Flutter Food Delivery App – part 2 (search bar)

food_delivery_app_2

Let’s wrap some padding around our TextField.

We use EdgeSet.all for put padding around the TextField.

We then EdgeInset for the inner padding of the Textfield.

home_screen.dart