Let’s start coding

Simple Startup app

First of all we are going to make a basic Flutter app which has a simple app bar with search and other options.

The code is pretty straightforward except I am rendering my own AppBar DefaultAppBar() and that looks something like this

There are couple things that I would like to point out here

In order to use any widget as AppBar you must implement PreferredSizeWidget. We are implementing a Stack here, so basically when user switches to search mode we will add search bar to this stack, which will get rendered at the top.

So with this much code we should have a simple flutter app with basic app bar.

Get Tap Location

Now in order to transition from default app bar to search bar with ripple animation we need to find out where user tapped on search icon (our trigger for search mode) so that we can start ripple animation from that location, we can start ripple animation from button itself but WhatsApp starts ripple animation from the point user tapped on search icon so we will also try to implement something like that.

Normal onPressed callback of search IconButton does not gives us location where user tapped so we are going to use GestureDetector’s onTapUp callback which does pass info about tap action.

In above code we are simply wrapping our search button in GestureDetector and we are registering a onSearchTapUp for onTapUp event, in this callback function we will get information about tap TapDetails details as first argument and that argument will provide us location of tap.

Now let’s learn how to draw that ripple animation.

We are going to draw that ripple animation by ourselves using CustomPainter.

Over here we have created a widget which extends CustomPainter class.

To draw ripple animation all we need is a point on screen (center) and draw a filled circle using that point as center with an increasing raidus.

But if we do just that then it will pain over entire screen (including all widgets that we might have in our Scaffold’s body) so we need a way to clip the circle so that it only draw over a certain region (in our case that region will be AppBar + StatusBar), so I am passing containerHeight to this widget (which will be height of our app bar) and it will add statusBarHeight to this value, and then it will clip the portion using

double regionHeight = containerHeight + statusBarHeight;

double regionWidth = screenWidth; canvas.clipRect(Rect.fromLTWH(0, 0, regionWidth, regionHeight));

and then we are drawing circle with specified color on that canvas using

Paint circlePainter = Paint();

circlePainter.color = color; canvas.drawCircle(center, radius, circlePainter);

Now lets add this Painter to our AppBar

So basically we are going to run an animation which will pass ever increasing radius value to our custom painter and passing the tapped location as center.

In this update we

registered our Animation (_animation)and AnimationController (_controller) in our Page for ripple animation. start animation (_controller.forward()) when user taps on screen. using MyPainter and Tapped location start a ripple animation which will span from 0% to 100% of screen by increasing the radius of drawn circle from 0 px to screenWidth px.

So with this much code we’ll have something like this

Now we’ll add search bar to our screen

At this point we don’t have anything related to our search bar so lets add that, search bar will appear as soon as the ripple animation ends, so to listen to animation end event we’ll register our status listener to animation controller.

Our search bar will be pretty basic, it’ll have a back button to go back to default app bar and an Input text where user can enter search query.

so with this setup we will be seeing our basic search bar appear when ripple animation ends.

Now we will wire up everything properly

Now we have basic version ready but there are still few things missing

search value is not passed to DefaultSearchBar. there’s no way for a user to return to default app bar state once he/she enters search mode.

Let’s first tackle going back to default mode from search mode.

That’s pretty easy to do all we have to do is pass a function to SearchBar which will execute when user pressed back button in search bar.

That function will run the animation in reverse direction, therefore it’ll look like the ripple animation going in backwards directly which is pretty cool

and then we will have to set that isInSearchMode variable as false which will remove SearchBar from the stack.

Now let’s handle passing value from search bar to default bar which we can do by passing another callback function which will get called when value of search input fails.

last but not the least we’ll also handle clearing input button which is added as suffix to the search input.

register these callback functions in search_bar.dart and wire them with proper widgets

And we’re done, we’ve added ripple animation for cool looking app bar transition we also wired up all widget event into the UI.

Conclusion

Flutter is an amazing and really flexible mobile development framework. We have built transition to switch between default toolbar and search bar which looks really amazing.

Github Repo: https://github.com/NishantDesai1306/flutter_search_bar_transition