Session 3: User Interfaces

An Introduction to User Interfaces in Android

Welcome back to Hack School! It's currently Week 4 at UCLA aka midterm hell week, but who needs to study for midterms when you have Hack School. Last week, we covered Java, which controls the "backend" logic of your app. This week we'll be covering the UI/Design of your app.

Announcements
  1. Hack on the Hill 2 (HOTH) is this Saturday (Feb 11)! If you’ve RSVPed, but aren’t sure whether to come (swamped with projects or midterms), you can come to HOTH and get some extra help.
  2. All projects for hack school submitted by this weekend will be PENALTY FREE (Yes, even for the one from Session 1)!
  3. PRIZES FOR HACK SCHOOL: Did we mention there are prizes for the top three teams by the end of this quarter? Come to win — and see you all tomorrow!

If you missed today's session, here are the relevant resources: Slides, Screencast

If you haven't yet joined, we have also launched a new ACM Hack slack. If you want to network with other students in Hack School, get help on projects, or just want general questions answered then register at the following link: https://hackucla.slack.com/

Topics

The topics we'll be covering are as follows:

  • Views
  • Layout Files
  • Layout Views
  • Animations

Views

Views or View Objects are the Visual Components that make up your app. You've been using these for the last few weeks. Some examples are: TextView, ImageView and Button.

Properties

Every View has properties/attributes. These properties affect various features of the View. Properties can affect size, color, shape and many other attributes. Some are required like "layout_width" and"layout_height". Others are optional like "onClick" and "layout_marginTop"

picture of properties

Visibility

Views have many associated methods and properties. One useful property is visibility. By manipulating this property, views can be made visible or invisible through code.

LinearLayout layout = (LinearLayout) findViewById(R.id.myLayout);  
layout.setVisibility(View.INVISIBLE);  
layout.setVisibility(View.VISIBLE);  

Layout Files

These are XML (eXtensible Markup Language) files that contain the 'code' for your app's design. XML is similar to HTML and consists of a tree-like structure of 'Views' (visual components).

Example of XML structure

<Parent>  
  <Child />
  <Child />
</Parent>  

In this example, we see that the 'Child' elements are inside of a larger 'Parent' element.

Simplified Android example

<LinearLayout>  
  <ImageView />
  <TextView />
</LinearLayout>  

Here we have an ImageView and TextView inside of a LinearLayout.

Layout files can be found in your res/layout folder
picture of res/layout folder

Text Tab

Once you open up a layout file, you will see the following screen
picture of layout file screen

This tab has the XML representation of your design. This gives you maximum control. You can add Views and manipulate properties easily.

Design Tab

The design tab is a bit more complicated. This tab has a visual display of your app. It also has a simple drag and drop interface that allows you to design your app without typing a line of XML. You can easily move around Views and edit their properties.

drag and drop image

Component Tree

In the top right of the design view is something called the component tree. This is a representation of your app's visual hierarchy. It shows a clear relationship between Parent Views and Child Views.
component tree image

Palette and Properties

The Palette has a list of Views that you can drag onto your layout. The properties tab allows you to edit various properties of your selected View.
palette and properties image

Layout Views

Layout Views (not layout files) are containers for other views. They determine the structure of the Views they contain. There are many different kinds of Layouts, and I'll go into a few of the more popular ones below.

RelativeLayout

In this layout, the Views are arranged relative to each other. You might tell one Button that it should be one inch away from an image above it. This layout gives you maximum control and flexibility, but it can be difficult to get things right.

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout           xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.mitrikyle.hellowarld.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
</RelativeLayout>  
LinearLayout

All the Views are in line either horizontally or vertically. This is a simple and easy to use layout.

<LinearLayout  
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="faded"
            android:id="@+id/faded"
            android:onClick="fadeOut"
            android:nestedScrollingEnabled="false" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="high af"
            android:id="@+id/high"
            android:onClick="flyIn" />
    </LinearLayout>
GridLayout

This type of layout allows you to arrange your Views in a grid structure with rows and columns. It is very useful for things like a photo gallery.

<GridLayout  
        android:layout_width="match_parent"
        android:layout_height="360dp"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:columnCount="3"
        android:rowCount="3"
        android:background="@drawable/board"
        android:layout_alignParentEnd="true"
        android:id="@+id/gridLayout">

        <ImageView
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:id="@+id/imageView"
            android:layout_row="0"
            android:layout_column="0"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="10dp"
            android:layout_marginRight="10dp"
            android:layout_marginBottom="10dp"
            android:onClick="dropIn"
            android:tag="0" />

        <ImageView
            android:layout_width="90dp"
            android:layout_height="90dp"
            android:id="@+id/imageView2"
            android:layout_row="0"
            android:layout_column="1"
            android:layout_marginTop="10dp"
            android:layout_marginLeft="25dp"
            android:onClick="dropIn"
            android:tag="1" />

    </GridLayout>

Animations

Android makes it easy to do cool animations. You just need to tell Android what you want to animate, the final state of the animation, and how long you want the animation to last. The animation will transform the object from its current state to the final state that you selected, over the duration you specified.

In code you need to
1. Get a reference to the View
2. Call the animate() function
3. Say what you want the final state to be, e.g rotation(360)
4. Specify a duration with setDuration()

ImageView image = (ImageView) findViewById(R.id.myImage);  
image.animate().rotation(360).setDuration(1000);  

Now I'll go into some specific types of animations

Fade

You can make a View fade in or out by manipulating the alpha property. 'Alpha' represents the transparency of an image from 0 (invisible) to 1 (completely visible)

image.animate().alpha(0f).setDuration(100); // fade out  
image.animate().alpha(1f).setDuration(100) // fade in  
Translate

You can move Views around the screen by manipulating their X and Y coordinates.

image.animate().translationYBy(1000f).setDuration(1000);  
image.animate().translationXBy(1000f).setDuration(1000);  
Rotate

You can spin things around by specifying an angle.

image.animate().rotation(180).setDuration(1000);  
Chaining animations

Animations can be chained together to make multiple things happen at once.

image.animate()  
     .translationXBy(1000f)
     .rotation(180)
     .setDuration(1000);
Setting up for animation

Some animations require setup. For example, if you want to slide something into the screen then it has to start off outside the screen. And Fading an image in requires that it starts off invisible.

image.setTranslationX(-1000f); // Set the position of the View to be off the screen to the left so you can slide it in later

image.setAlpha(0f) // Make image invisible so you can fade it in later

Mini Project

dat boi

We're going to create a small project that will use some of the animation and layout things that you've just learned. Create a new empty project and let's begin.

Setup the image

Download the datboi image above, and paste it into your res/drawable folder.

Rename your image to "datboi".

Setup the layout - res/layout/activity_main.xml
  1. Delete that annoying hello world text
  2. Go into the XML and change the <RelativeLayout> to a <LinearLayout> with vertical orientation
  3. Place an <ImageView> on top in the center
  4. Place a <LinearLayout> with horizontal orientation below the <ImageView>
  5. Place two buttons inside this inner <LinearLayout>
  6. Change the <ImageView> "layout_height" and "layout_width" to 200dp
  7. Change the <ImageView> "layout_marginTop" to 100dp
  8. Change the <ImageView> "id" to be “datboi”
  9. Change the <ImageView> "src" property to be your image : @drawable/datboi
  10. Change the inner <LinearLayout> "layout_width" to be "wrap_content"
  11. Change the left button’s text to “faded” and id to “faded”
  12. Change the right button’s text to “high af” and id to “high”
  13. Change the “faded” button’s onClick property to be “fadeOut”
  14. Change the “high” button’s onClick property to be “flyIn”

Your final layout code should look like this (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.mitrikyle.datboi.MainActivity">

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:id="@+id/datboi"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="100dp"
        android:src="@drawable/datboi" />

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="faded"
            android:id="@+id/faded"
            android:onClick="fadeOut"
            android:nestedScrollingEnabled="false" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="high af"
            android:id="@+id/high"
            android:onClick="flyIn" />
    </LinearLayout>
</LinearLayout>
Add the animations in Java - MainActivity.java

Write the following in your MainActivity.java

Write the fadeOut function
// Will be called when the "faded" button is clicked
    public void fadeOut(View view) {
        ImageView datboi = (ImageView) findViewById(R.id.datboi);
        datboi.setAlpha(1f); // reset the image to fully visible
        datboi.setRotation(0f); // reset the image rotation
        datboi.animate().alpha(0f).setDuration(2000); // fade out over 2 second (2000ms)
    }
Write flyIn fucntion
// Will be called when the "high af" button is clicked
    public void flyIn(View view) {
        ImageView datboi = (ImageView) findViewById(R.id.datboi);
        datboi.setAlpha(1f); // reset the image to fully visible
        datboi.setRotation(0f); // reset the image rotation
        datboi.setTranslationX(-1000f); // take the image off screen to the left
        datboi.setTranslationY(-1000f); // take the image off screen to the top
        datboi.animate()
                .translationYBy(1000f) //  bring the image back in the screen from the top
                .translationXBy(1000f) // bring the image back in the screen from the left
                .rotation(720) // rotate the image 720 degrees
                .setDuration(2000); // do this over 2 seconds (2000ms)
    }
Watch the magic happen

final pic

Let's get some points!

For beginners you can solve all of the exercises and receive points for completing those. For intermediate/advanced students you can work on the weekly project with your team, and receive points for completing that. You can only get credit for one or the other, but not for both so choose the one most appropriate for your skill level. Please only submit one .zip file per team. Include the contents of your entire android project, and also provide your team access code in a text file. Otherwise you will not receive credit!

Grading

Submissions will be due 1 week from the session, but we will accept late submissions taking some points for each day it is late. The lateness penalty for an assignment that is submitted between N and N+1 full days late (where N is nonnegative) is 2^N % of the assignment's value. That is, the penalty is 1% for being up to 1 day late, 2% for being from 1 to 2 days late, 4% for being from 2 to 3 days late, and so forth.

Exercises

Exercise 1:
  1. Attempt to create the following using relative layout. You don't have to use these colors, you can pick your own.
Exercise 2:
  1. Attempt to create the following using linear layout. You don't have to use these colors, you can pick your own.
Exercise 3:
  1. Choose two random images on the web
  2. Create two ImageButtons using the chosen images
  3. Overlay one button above the other using relative layout
  4. When screen is pressed one image should fade in and the other should fade out. When pressed again the current image should fade out, and the other should fade in.

Project 3

For the third project we will be building out a tic-tac-toe game using the layout and animation techniques learned today. The goal is to build out this project with your team based off the knowledge gained from this section. If you are feeling confident you can attempt to complete the project without the skeleton, but it will be a lot easier if you use it. We will be uploading the project solution towards the end of the week, so if you haven't cracked it by then look at the solution to learn the correct implementation.

Instructions

The goal is to build a tic tac toe game with as little guidance as possible, so try to come up with unique solutions when you run into problems. You're being given lots of flexibility so come up with your own implementation: grading will be very generous. You should implement the two functions left blank in Main Activity and finish the xml file to add in the remaining UI.

dropIn function
  • This function should be used to drop in image views when pressed
  • It should update the game state and active player
  • It should determine if somebody has won the game
  • If game is over it should display a dialog indicating winner
  • It should check for draws
  • Optional: Add in cool animation that causes tiles to fly in or fade in
playAgain function
  • Should reset game to initial state, and update all variables
  • It should hide dialog box
Hints
  • Start with the xml layout and add in missing image views for tiles
  • Look up creative uses for tags
  • Onclicklistener is not needed when the xml has it already defined
  • Linear Layouts can also be added using id in the code
  • layout.setVisibility(View.INVISIBLE) can set a view to be invisible

Here is the link to the project skeleton: https://github.com/uclaacm/Hack-School-Winter-Session-3