Your First Flutter App: Polishing the App

Apr 12 2022 · Dart 2.14.1, Flutter 2.5, Visual Studio Code

Part 3: Style the App

25. Style the Slider Thumb

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 24. Style the Slider Next episode: 26. Conclusion

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 25. Style the Slider Thumb

Our slider looks really good, but it would be nice to upgrade the thumb. We want to add a custom image to it that looks like bullseye. Now, there are a couple of challenging aspects when updating the thumb. We first need to get the image from our app bundle.

The app bundle is just a single package. When you add images to your project, they are copied to the app bundle.

We need to get our image and convert it to a ui image which requires some advanced code.

Of course, once we have the image, we need to tell Flutter how to draw it by using Flutter’s drawing commands. The following code is going to be a little complex. My advice - just follow along, look for familiar patterns and just get used to writing Flutter code. Don’t try to understand everything at once. Let’s begin.

Open your project in progress or download the starter project for this episode. We’re going to start by creating a class that extends from the SliderComponentShape. This is the base class for the slider thumb.

Start by creating a new file called, slider_thumb_image.dart. Import the material library and the dart ui package.

import 'package:flutter/material.dart';
import 'dart:ui' as ui;

Next, create a new class called SliderThumbImage.

class SliderThumbImage extends SliderComponentShape {

}

Next create a property for a ui image. This is used for drawing images.

final ui.Image? image;

Then we’ll add a constructor to actually set the image.

SliderThumbImage(this.image);

Then we’ll set the preferred size of the image. We’re going to be painting the image so we’ll set this zero.

@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
  return const Size(0, 0);
}

Now comes the fun part. We’re gong to override the paint method. This takes in a lot of parameters. We won’t be using them but they are required nonetheless

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required bool isDiscrete,
    required TextPainter labelPainter,
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required TextDirection textDirection,
    required double value,
    required double textScaleFactor,
    required Size sizeWithOverflow,
  }) {

  }

Next, we create a variable that holds the image property.

final thumbImage = image;

After which we’ll check to make sure that the variable isn’t null. Null means no value.

if (thumbImage != null) {

}

Then we get the canvas.

final canvas = context.canvas;

After which, we set the offset based on the width and height. we divide by two because we want the image centered.

final imageOffset = Offset(
    center.dx - (thumbImage.width / 2),
    center.dy - (thumbImage.height / 2),
);

Next we create a new paint object and set the filter quality on it.

var paint = Paint();
paint.filterQuality = FilterQuality.high;

Finally, we draw the image.

canvas.drawImage(thumbImage, imageOffset, paint);

Okay, believe it or not, that was the easy part of the code. Next comes the tricky part. We’re going to be using some advanced language features. Like I mentioned, just follow along. Open up control.dart. We’re going to import some packages.

import 'slider_thumb_image.dart';
import 'dart:ui' as ui;
import 'package:flutter/services.dart';

We import the slider thumb to use. We’ll also be using some classes from the dart ui package as well as the services package.

We’re going to create a new property for the _ControlState class for the slider image.

ui.Image? _sliderImage;

Now we’ll write a new method to load an asset from the package. We’re using a future which means we’ll get a result some time in the future.

Future<ui.Image> _load(String asset) async {

}

Next we’ll get the data from your app bundle.

final data = await rootBundle.load(asset);

Then, we will call a method to get an image codec passing in a buffer from the data.

final codec = await ui.instantiateImageCodec(data.buffer.asUint8List());

After which, we’ll get the frame from the codec.

final fi = await codec.getNextFrame();

Finally, we return an image from the load method.

return fi.image;

Now, let’s call our new method in init state. This method is called each time the widget resets.

@override
void initState() {
  _load('images/nub.png').then((image) {
      setState(() {
      _sliderImage = image;
      });
  });
  super.initState();
}

We load the image using the load method. We use the then to respond to the load method. This is covered later in this learning path. Then we set the state, setting our new image.

Now, lets set our new thumb image. Down in the slider theme, lets add it to the thumb shape property.

thumbShape: SliderThumbImage(_sliderImage),

And that’s it. Save and switch back to your app and hot reload. And now we have a bullseye thumb. Well done!