Adding a Progress Bar in React Native: A Step-by-Step Guide

When designing user experiences for your app, you may decide to show or hide widgets as conditions change in the app, such as in response to user actions or to adapt to available space on the screen.
Consider a calculator app, for example. If the calculator is in portrait orientation, then the advanced scientific keys may not be visible, but if it’s in landscape orientation, then all the scientific keys can be visible.
Showing and hiding widgets could also be useful when designing a data visualization user interface, where you can selectively hide a component, such as a pie chart segment.
Another application is when designing a game. For example, when a player knocks an object, it can disappear from the scene.
Flutter provides a widget named Visibility to enable these types of user experiences. In this tutorial, we’ll
The Flutter Visibility widget contains a number of properties to enable customizing its behavior. This provides the Visibility widget with a lot of flexibility for various use cases.
For a complete list of Visibility widget properties, you can review the details on flutter.dev. In the next section, we’ll learn how to define a basic Visibility widget.
Creating a Visibility widget is easy. Simply set the widget that you want to control to the child property, and set a boolean variable to the visible property.
Below is an example use case of Visibility. Here, we’re building a column of widgets embedded in a Card. In the card, there’s an image displayed as the second item in the column, wrapped in a Visibility widget.
Notice how we assign the variable imagesVisible to the visible property of the Visibility widget. By dynamically updating the imagesVisible variable, we can make the image appear or disappear from the card.
Card buildCard(Map<String, dynamic> cardData) {
return Card(
elevation: 4.0,
child: Column(
children: [
ListTile(
title: Text(cardData['heading']!),
subtitle: Text(cardData['subheading']!),
trailing: Icon(Icons.favorite_outline),
),
Visibility(
visible: imagesVisible,
child: Container(
height: 200.0,
child: Ink.image(
image: cardData['cardImage']!,
fit: BoxFit.cover,
),
),
),
Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: Text(cardData['supportingText']!),
),
ButtonBar(
children: [
TextButton(
child: const Text('CONTACT AGENT'),
onPressed: () {/* ... */},
),
TextButton(
child: const Text('LEARN MORE'),
onPressed: () {/* ... */},
)
],
)
],
));
}
For our demo, we’ll build upon the real estate app that we created in my previous post How Do I Create a Flutter Card? Examples and Use Cases. We’ll modify the app to give the user the ability to show or hide photos.
This demo app doesn’t depend on any third party libraries. Therefore, you can use DartPad to follow along. DartPad is a web-based editor where you can try out Flutter code without the need to install anything on your computer. To follow along with this tutorial, head over to https://dartpad.dev/
Below is what the final app will look like.
The first step is to create a basic app shell as a foundation to start us off. Paste the code below into your code editor and run the app. You should see an AppBar with the title “Flutter Visibility Demo.” In the body section, you should see the text “Flutter Visibility Demo” in the center of the screen.
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light(),
debugShowCheckedModeBanner: false,
home: MyHomePage(title: 'Flutter Visibility Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({this.title = 'Demo'});
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black45,
title: Text(widget.title),
),
body: Center(
child: Text('Flutter Visibility Demo'),
));
}
}
Next, we declare our two state variables. The first, imagesVisible, controls whether or not the photos in the cards appear. The second variable, cardContent, will be populated with content that will be displayed inside our real estate property cards in the next step.
class _MyHomePageState extends State<MyHomePage> {
var imagesVisible = true;
var cardContent = [];
...
Let’s now generate all the content that will go into the real estate property cards. Since this is only a demo, we’ll create random content for the cards. In a real world app, this data would be sourced from a database.
Add the initState function below to the _MyHomePageState class. This will create the content we need for each card’s heading, subheading, image, and supporting text.
class _MyHomePageState extends State<MyHomePage> {
...
@override
void initState() {
var ran = Random();
for (var i = 0; i < 5; i++) {
var heading = '\$${(ran.nextInt(20) + 15).toString()}00 per month';
var subheading =
'${(ran.nextInt(3) + 1).toString()} bed, ${(ran.nextInt(2) + 1).toString()} bath, ${(ran.nextInt(10) + 7).toString()}00 sqft';
var cardImage = NetworkImage(
'https://source.unsplash.com/random/800x600?house&' +
ran.nextInt(100).toString());
var supportingText =
'Beautiful home to rent, recently refurbished with modern appliances...';
var cardData = {
'heading': heading,
'subheading': subheading,
'cardImage': cardImage,
'supportingText': supportingText,
};
cardContent.add(cardData);
}
super.initState();
}
Next, we create a function that builds a single card. We can call this function multiple times to create as many cards as we need. Notice how we use the imagesVisible state variable to control the visibility of the card’s image.
Card buildCard(Map<String, dynamic> cardData) {
return Card(
elevation: 4.0,
child: Column(
children: [
ListTile(
title: Text(cardData['heading']!),
subtitle: Text(cardData['subheading']!),
trailing: Icon(Icons.favorite_outline),
),
Visibility(
visible: imagesVisible,
child: Container(
height: 200.0,
child: Ink.image(
image: cardData['cardImage']!,
fit: BoxFit.cover,
),
),
),
Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: Text(cardData['supportingText']!),
),
ButtonBar(
children: [
TextButton(
child: const Text('CONTACT AGENT'),
onPressed: () {/* ... */},
),
TextButton(
child: const Text('LEARN MORE'),
onPressed: () {/* ... */},
)
],
)
],
));
}
Now it’s time to add the cards to the body of our app’s Scaffold widget. The code below creates a scrollable list of cards. The code converts the card data that we generated in Step 3 into Card widgets.
body: Container(
padding: EdgeInsets.all(16.0),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children:
cardContent.map((cardData) => buildCard(cardData)).toList(),
)),
)
In this step, we add a switch that enables us to control the visibility of the card images. We’ll use a switch placed in the AppBar for this. When the switch value is changed, the value of the imagesVisible variable updates to match the value of the switch. Use the code below to set the appBar property for your Scaffold widget.
appBar: AppBar(
backgroundColor: Colors.black45,
title: Text(widget.title),
actions: [
Switch(
value: imagesVisible,
activeColor: Colors.yellowAccent,
onChanged: (bool switchState) {
setState(() {
imagesVisible = switchState;
});
},
),
]),
You should now have a fully working app. Make sure the show/hide feature works as expected. As apps get more complex, it’s important to test each new feature you add, while also ensuring that any existing features haven’t been broken. If you get stuck, you can refer to the full code listing here: https://dartpad.dev/?id=ddc9f12833ce0ed45f282332201a4712
In this tutorial, we learned how to use the Flutter Visibility widget to enrich a mobile app’s user experience to make it more dynamic and adaptive. We explored the properties of the Visibility widget that allow you to customize it to your needs. With this knowledge, you can build your own Flutter apps using the Visibility widget.
If you want to learn more, you’ll find a lot of useful content on mobile design, mobile engineering, QA & testing, and more on the Waldo blog.
This post was written by Daliso Zuze.Daliso is an expert in agile software delivery using Scrum. Besides that, he’s an experienced digital transformation consultant and entrepreneur. His technical skills center around mobile app development and machine learning.