Brushed Metal texture with Flutter

Ivan Cherepanov
6 min readOct 13, 2019

--

Let’s imagine you’re building an application for really tough guys. A motorbike shop. Located on the active volcano 🌋. On the island full of zombies 👤. In the middle of the acid ocean 🌊. On an alien planet 👽. In an inversed space-time dimension 💫. Diffused shadows and all the “paper” things are not tough enough for that. They even hardly agreed to create an app for their business, by the way. They simply wanted to enslave a whole civilization to send an arrow-ad man to every corner in the galaxy, to advertise their shop and record bookings for their roaring monsters, but somebody told them it would be bad for PR 😶.

When you visited their shop first time, you thought you might have recognized one of your discoveries in “No Man’s Sky”

So it’s really tough, and you have to stand to it.

So you present them with this first version of the app (starting source code under the link).

That button…

Reviewing login and signup screens, and slowly getting to the holy grail of this application — bikes catalogue.

And everything goes relatively well (you’re not beaten to death with your limbs dismembered from your pathetic body). Well, until something really bad happens…

“IT IS BLUE!” — proclaimed by one of your clients. You see that for sure and preparing yourself to hear about the penalty for such an obvious mistake. But then the face of shop owner changes and its usual anger and rage сedes place to curiosity, while he says: “IT DOESN’T FEEL LIKE US, LITTLE HUMAN”.

“THIS SMALL PIECE OF PAPER WON’T SURVIVE HERE LONG” he adds.

And that it’s true, in fact, your spacesuit beeps of life support system malfunction for the last 20 minutes.

“USE METAL”, says the owner visibly proud of his savvy eye. “BRUSHED METAL, WE WANT OUR CUSTOMERS TO BE EXCITED.” and falls silent.

The rest of the presentation goes smoothly and you happily depart in one piece. What a trip.

“Brushed metal texture” is what your first search query looks like the next day. But nothing looks quite like you want to see it. Some textures have unnecessary gradients, some just look boring and washy, some doesn’t have scratches look nice enough. Everyone was there. Time goes by as you understand — it’ll be quicker to write it yourself then find what you need.

Luckily Flutter allows you such freedom. You start with scaffolding a CustomPainter for this BikeButton.

And keep the BikeButtonPainter itself simple, for now.

Also, the whole button container was very flat, so you add a bit of depth to it, explaining where the list goes when it scrolls behind the button.

We can only hope this shadow is not too soft for them.

Not that bad you think, yet someone still has to brush that chunk of grey boringness. Brushing metal is very simple, you just need a very stiff brush and a lot of patience. Or an electric tool to create that linear motion. To re-create that look, you think that semi-transparent lines might do, overlapping each other randomly.

For that, you add a new helper inBikeButtonPainter to return an arbitrary Offset within given Size.

As well as new paint, to draw those lines.

And simply generate a few of these lines in the button body you got.

The result is disappointing. At best. You feel that a tiny cold worm starting to unroll itself somewhere in your stomach. “More lines,” you think.

But despite tenfolding the line count… It doesn’t look ten times better. The worm grows bigger and colder.

“Maybe even more lines?” you think.

But that just leaves you to stare to a white mess. There’s no button anymore.

You realize that there could be too many lines. “How do I find the optimal count to fit all sizes? Maybe I can compute count based on the size itself?”

That’s looking a bit better already, allowing you to customize how the texture looks, regardless of its area.

Then, you think that the current brush is a bit too random, in reality, all the scratches would be aligned almost precisely. So instead of two random points, you decide to choose only one and add another one with a stricter rule.

Luckily, Dart allows doing that easily. Offset class implements most of the algebraic operators, so you can just do all the cool vector addition inline!

So, now, you align the points on a straight horizontal line.

Someone applied “wind” effect to this button.

And the button now looks like it tries to escape your application before it’s too late.

You think that one of the easy ways to fix this behaviour is simply to clip unwanted parts of the texture. And that couldn’t’ve been simpler with Flutter.

Alongside the Flutter itself being a cake 🍰, dart:ui Canvas is sort of cake too, when it comes to drawing on it. Your usual workflow is to call canvas.save(), then apply modifications you created a layer for, and then call canvas.restore(). Simple and elegant.

So, in this case, you want to clip drawn area to the size of your button.

Looks a bit better, but now it’s asymmetrical. To fix that, you want the lines to start and end in equal areas from the rectangle borders.

Then, you tweak displacement values in various ways trying to find the right angle for scratches.

You put different numbers in displacement offset to see how it changes the scratch texture.

Another thing you could think of is that all of your lines are of the same colour. You can imagine them having slightly different tints in reality. So you swap linePaint with linePaints and add a helper to choose Paint from it randomly.

So, the next step for you is to add that distinct look of Brutalinium, the favourite metal of those merchants. It has distinctive red-blue hues when exposed to the acid atmosphere of their homeworld long enough. No problem, let’s just add these to linePaints.

You’re not sure who called this alloy Brutalinium, cause it looks as happy as brushed metal could be.

You tweak parameters for another hour. And add GestureDetector over CustomPaint in BikeButton. Cold worm releases its hold and you’re looking forward meeting those guys next week.

Thanks for reading this article! I hope that you learned something new, or at least didn’t waste your time reading it. Please feel free to share your story of drawing custom interfaces with Flutter down below, or just write me a few lines to av@av.codes, I would appreciate that!

📝 Read this story later in Journal.

👩‍💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. Read the Noteworthy in Tech newsletter.

--

--