Skip to main content

01 - Layouts

View

This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. Any other UI components (eg: buttons, text fields, etc) are extentions of the View.

Views also respond to user actions. For instance, when a user taps a button (which is a View), the event is handled in the View. If you want to trigger something when the user taps a button, the View is also exposing listeners (callbacks) for such events.

Layouts

In Android, layouts are used to define the structure and arrangement of the user interface (UI) elements on the screen. A layout is a container that holds UI components like buttons, text views, and images. It organizes these components either in a specific arrangement or based on user-defined constraints. Android provides several types of layouts, each with a different method for positioning UI elements. Some examples are: Linear Layout, Relative Layout, Grid Layout, Constraint Layout.

Linear Layout vs Relative Layout

Linear layout

Arranges its children in a single row (horizontal) or column (vertical). It creates a scrollbar if the length of the window exceeds the length of the screen.

Example

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="horizontal"
android:gravity="center">

<!-- Include other widget or layout tags here. These are considered
"child views" or "children" of the linear layout -->

</LinearLayout>

Width and Height attributes

Attributes android:layout_height and android:layout_width are used to specify the size of an element. This attributes are required for any view inside of a containing layout manager. Their value may be a fixed dimension (such as "12dp") for a constant size or one of the special constants from the table below.

match_parentWill force the view to expand to take up as much space as is available within the layout element it's been placed in (its parent), minus the parent's padding, if any.
wrap_contentThe view wll be large enough to fit its own internal content, taking its own padding into account.

Specific attributes for LinearLayout

Views

TextView

A user interface element that displays text to the user.

Example

 <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text_view_id"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/hello" />
</LinearLayout>

android:id attribute

Allows you to identify an element (either a layout of a view) either in the xml file (when using relative based layouts) or in the Activity (to bind to the view and control it or change its attributes). It is recommended to add it for the views that you want to have access to in the Activity (for example: if you want to change the displayed text or if you want to receive click callbacks from buttons).

android:text attribute

Allows to specify the text to be displayed by the view element. Is also available for buttons or other views displaying a text.

EditText

A user interface element for entering and modifying text.

Example

 <EditText
android:id="@+id/plain_text_input"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:inputType="text"/>

android:inputType attribute

This attribute must be specified for each EditText element. For example, for plain text, the input type will be "text".

Choosing the input type configures the keyboard type that is shown, acceptable characters, and appearance of the edit text. For example, if you want to accept a secret number, like a unique pin or serial number, you can set inputType to "numericPassword". An inputType of "numericPassword" results in an edit text that accepts numbers only, shows a numeric keyboard when focused, and masks the text that is entered for privacy.

android:orientationused to specify whether the child views are displayed in a column or in a row
android:gravityspecifies how an object should position its content, on both the X and Y axes, within its own bounds
android:layout_weightIndicates how much of the extra space in the LinearLayout is allocated to the view associated with these LayoutParams.

Button

A user interface element the user can tap or click to perform an action.

Example

 <Button
android:id="@+id/first_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/self_destruct" />
class MainActivity : AppCompatActivity() {
private lateinit var first_button: Button;
private lateinit var second_button: Button;

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// First method of adding a click listener
first_button = findViewById(R.id.first_button);
first_button.setOnClickListener {
val toast = Toast.makeText(this, "Hello World!", Toast.LENGTH_LONG);
toast.show();
}

// Second method of adding a click listener
second_button = findViewById(R.id.second_button);
val listener = object: View.OnClickListener {
override fun onClick(p0: View?) {
val toast = Toast.makeText(this@MainActivity, "Hello World!", Toast.LENGTH_LONG);
toast.show();
}
}
second_button.setOnClickListener(listener)
}
}

Radio Button

Radio buttons let the user select one option from a set of mutually exclusive options

Example

<?xml version="1.0" encoding="utf-8"?>
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton android:id="@+id/radio_pirates"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pirates"/>
<RadioButton android:id="@+id/radio_ninjas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ninjas"/>
</RadioGroup>
findViewById<RadioButton>(R.id.radio_pirates).setOnCheckedChangeListener { buttonView, isChecked ->
Log.d("RADIO", "Pirates is checked: $isChecked")
}

findViewById<RadioButton>(R.id.radio_ninjas).setOnCheckedChangeListener { buttonView, isChecked ->
Log.d("RADIO", "Ninjas is checked: $isChecked")
}

Project structure

Logcat Logcat
  • app/
    • src/: The source code folder.
      • main/: This is the main source set for your app. It contains both your Java/Kotlin code and resources.
        • java/: Contains all the Kotlin or Java source files for your app. This is where your Activity, ViewModel, and other classes go.

          Example: com.example.myapp.MainActivity.kt (for Kotlin) or MainActivity.java (for Java).

        • res/: This directory contains all non-code resources (like images, layouts, strings, etc.). Subfolders include:

          • layout/: XML files that define the layout of your activities and fragments (UI elements).

            Example: activity_main.xml

          • drawable/: Image files (PNG, JPEG, SVG), vector drawables, and other graphics.

          • values/: XML files that contain constant values like strings (strings.xml), dimensions (dimens.xml), colors (colors.xml), and styles (styles.xml).

          • mipmap/: Contains launcher icons for different screen densities.

        • AndroidManifest.xml: The manifest file that declares app components, permissions, and other app-wide configurations.

Logs

System logs are the most important information that DDMS can provide. System logs describe all the actions performed by the device, the exceptions that occurred, and the information required for troubleshooting. The logs will appear in the panel named LogCat (do not confuse with Console). Each message in this list is accompanied by the following data:

Type of message
I Informationinformative message
D Debuguseful debugging message
W Warningwarning message (exceptions that are not very important and do not have an important impact on the component appear as such messages)
E Errorerror message (exceptions that break a component appear as such messages)
V Verboseadditional information displayed by the programs (generally on request, they are used to detect problems generally resulting from misconfiguration of programs)
TimeDate and time at which the message was written
PIDThe ID of the prosses that generated the message
TagLabel or category of message (useful for filters)
MessageThe actual message

Example

class MainActivity : AppCompatActivity() {
private lateinit var firstButton: Button
private lateinit var secondButton: Button
private lateinit var editText: EditText

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// First method of adding a click listener
firstButton = findViewById(R.id.btn)
firstButton.setOnClickListener {
BUTTON_PRESS_COUNTER += 1;
Log.d(TAG, "Pressed this button $BUTTON_PRESS_COUNTER times");
}
}

companion object {
var BUTTON_PRESS_COUNTER = 0;
var TAG = "MainActivity"
}
}
Logcat
Logcat

Exercices

  1. Use the layout elements explained in the lab to design an xml layout looking similar to the one below.
BMILayout
  1. Create the MainActivity file associated to the xml layout and bind all the needed elements of the layout (for example: the button might be needed to add a click listener to it).

  2. In onCreate function, write logs (Verbose, Debug, Info, Warning, Error). View them with the Logcat.

  3. Add a click listener for the Calculate button that logs all the information entered by the user.

  4. Override al the lifecycle methods and add logs on each one. The log message must contain a message specific to the event triggered. For example in the onCreate() callback you can write "onCreate has been called". Run your app and see the order in the callbacks get triggered.

  5. When pressing the calculate button, gather all the information from the user and compute the BMI by the following formula BMI = weight / height_squared. Display the resulting BMI on the screen, along with an indication about the BMI of the user.