Skip to main content

Remote Flying Fish Project Part 14: Flutter UI Design

In this chapter, we will create a simple interface of our mobile application by Flutter.

First, click "Start a new Flutter project".

Screen showing Android Studio

Select "Flutter Application".

Screen showing creation of New Flutter Project

Type in the project name and select the folder of Flutter for Flutter SDK path.

Screen showing how to create project name and SDK path

Remain in the default settings and click "Finish".

Screen showing - set the package name

You may have a similar interface shown up as below.

Interface screen

Now, you may see "No devices" on the upper bar, which means you have not connected any device either physical or virtual.

Screen showing no devices have been connected

Select "Tools" → "AVD Manager".

within tools select AVD manager

Click the "Run button" in "Actions".

Click Run button in Actions

A virtual device shows up.

Image of a virtual device

Now you can see your virtual device on the upper bar.

virtual device shown on the upper bar

Let's move on to the coding. Insert the following codes to import the resources for Flutter. Note that some of the rows are int grey, which means it has not yet be used.

codes to import the resources for Flutter

First, we fixed the orientation of mobile horizontally (default vertical) in the void main function.

Remark: we will move this part into initState() later

Making the screen landscape by changing the code

Then we need to separate the screen into two parts, left for controlling the horizontal direction and right for controlling the vertical direction. Follow the steps below.

1. Modify the MyApp() function into Setup()

2. Change the title name to "Flying Fish Controller".

3. In the MaterialApp() function, adding a Scaffold() in "home:" to create an App Bar and Row() in "body:" with multiple "children".

4. Inside the "children", you can use Expanded() to specify the percentage of the width. Let's say 70% for the left side and 30% for the right side.

5. Adding a container in "child:" with the colour you want. (i.e. light blue for left and yellow for right)

Code showing how to separate the screen into two parts

Delete the class "MyHomePage" and class "_MyHomePageState". Run the program (press shift + F10). You may see the result like this.

result of removing the "MyHomePage" or MyHomeState"

The next part is to create two joysticks in the left and the right region. We can use GestureDetector() to draw any shape. However, we need to first create it then create a container. Therefore, we have to delete the container first. Let's add a new class name HorizontalTouchControl() to replace the left container.

create joystick in the left regioncreate joystick in the right region

In this class, we defined some variables and constants for future use, it can let us detect whether we drag a joystick. So we create another class, HorizontalTouchControlState(), that to create GestureDetector.

code to detect whether we drag a joystick

We extend "State<HorizontalTouchControl>" and return a new GestureDetector in Widget build() function. You can see there are three void methods which represent "Start", "End" and "Update". When the user touches down the screen, it will display "start". Display "end" if touches up. We will discuss what to put inside later.

code showing there are three void methods which represent "Start", "End" and "Update"

Next, we create a new Container under the GestureDetector. You can see there is a new command called alignment, it can fix the origin coordinate (0,0) at a specific corner by different input, (-1.0, 1.0) for the left bottom, (1.0, 1.0) for the right bottom. We will use it in the implementation as we want to make sure it is suitable for all screen sizes of mobile.

Before drawing the joystick, we need several values, the radius of the joystick and the original coordinates (x,y) of the joysticks. As we mentioned, the origin for the left region is in the left bottom and the origin for the right region is in the right bottom. Also, the y-axis of the screen is negative if it is above the origin. Therefore, we can define the following variables at the top of the program.

defining the following variables at the top of the program

Also, we need the screen size of the mobile. So we create two more variables below those coordinates. (size_height and size_width)

code for screen size

However, we need to use "context" to get the height and width of the screen. Therefore, we have to separate the "MaterialApp()" by using a new class. We can get the height and width by "MediaQuery.of(context).size.height[width]".

Code to get the height and width

Create four variables in the class HorizontalTouchState to store the value of the original coordinates for future uses.

code to Create four variables

Create a new CustomPaint under the Container, create another class called HorizontalTouchControlPainter inside of it. (i.e. painter:) Remarks: for clear understanding, let's change the colour of the Container to default white colour by delete the "colour:" command.

Create a new CustomPaint under the Container

Override the paint() function, we need to create 3 different shapes, two lines, a big circle and a small circle. Therefore, we need to create three new Paints, "paint_dot", "paint_circle" and "paint_line". Remarks: the big circle should empty inside and the small circle should be filled.

Then draw the circles and the lines, be careful the start and the end coordinates of the lines.

Code to draw the circles and the lines

You may see the last line we override a boolean "shouldRepaint()", it will draw the dot again if the position is changed. Then the dot will follow your finger when you are dragging it.

The next step is to set the new coordinates to the variables when you are dragging the dot. You can use"setState() inside the _handlePanUpdate().

set the new coordinates

Now you can test your program on your virtual device. You can drag the dot in whatever place within the left region. The dot will follow your finger. However, you can see there are two mistakes, the big circle and the lines only fix in the original position. We want it to appear where we touch down the screen. The second mistake is the dot will stop at the position that we stop dragging. We want everything back to the original position including all circles and lines.

Therefore, we can add the commands inside the "_handlePanStart" and "_handlePanEnd". It can set the coordinates that you press on the screen and the original coordinates when you touch off the screen.

set the coordinates that you press on the screen

Here is the result, it looks much better.

The next step is to calculate the distance and the angle. Let create three variables at the top of the program, "distance", "angle" and "height". It is also the three variables that we send to the Arduino in the future part.

calculate the distance and the angle

Create two methods to calculate the distance and the angle.

calculate the distance and the angle

Remarks: Be careful of the y coordinate. Also, the output of using "atan()" is in radian. Change it to a degree by multiply 180 and divide pi.

Change it to a degree by multiply 180 and divide pi

Once we have the value of the distance and the angle, we can limit the dot inside the big circle. Also, adding a print command to see the results of distance and angle.

limit the dot inside the big circle and adding a print command

Congrats, you already finished the left region. We still have the right region. It is mostly the same as the left region but has some minor changes.

Replace the Container with a new class VerticalTouchControl.

Replace the Container with a new class VerticalTouchControl

Change the name from Horizontal to Vertical inside the class TouchControl.

Change the name from Horizontal to Vertical inside the class TouchControl

The four variables using the coordinate of the right region.

four variables using the coordinate of the right region

The alignment is set to (1.0, 1.0). The origin coordinate is set to (0, 0) at the bottom right corner.

alignment set to (1.0, 1.0)

The following class have some changes. We would like to use two new variables to store the distance(distance_R) and the angle(angle_R) of the joystick as we do not want to interrupt the variable "distance" and "angle". They are used to limit the dot move within the big circle.

two new variables to store the distance(distance_R) and the angle(angle_R)

Also, we will need to calculate the height. It is simple, move upward (output 1), move downward (output-1) and no move (output 0). You can simply compare the y-axis of the moving dot.

The calculation of distance and angle is more or less the same, but be careful the x-axis is in -ve sign.

calculation of distance and angle is more or less the same

2019-12-06_%285%29_b396771ca97b241172092c72ae889dd865d013fb.png

After all, there is only one more step to control the airship, sending messages to Arduino through Bluetooth. We will discuss it in the next chapter.

Parts in this series

Downloads

lokit has not written a bio yet…