IT272 Mobile Application Development

Mobile Application DevelopmentUnit 413 min read

UI Design & Layouts: Widgets, Views, XML, Constraints & Adaptive UI

Unit 4 of Mobile Application Development covers Android’s UI components (Views, Widgets), layout systems (Linear, Relative, Constraint), XML-based UI design, styling with themes and styles, and responsive/adaptive layouts for different screen sizes and orientations.

Core Concepts

Views and Widgets: The Building Blocks of UI

Definition:

  • View: The base class for UI elements (e.g., buttons, text fields). Every UI component is a View or its subclass.
  • Widget: A subclass of View that represents a basic interactive UI element (e.g., Button, EditText, ImageView).
  • ViewGroup: A subclass of View that can contain other views (e.g., LinearLayout, RelativeLayout, ConstraintLayout).

How They Work:

  • Views are drawn on the screen in a hierarchy (parent-child relationship).
  • The root view (e.g., ConstraintLayout) is the topmost container.
  • Views handle events (e.g., clicks, touches) via callbacks like onClickListener.

Example: Button Widget

<Button
    android:id="@+id/myButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me"
    android:onClick="onButtonClick"/>

Visual:

graph TD
    A["ConstraintLayout (Root ViewGroup)"] --> B["Button (Widget)"]
    A --> C["TextView (Widget)"]
    B --> D["onClickListener"]
    C --> E["android:text"]

Layout Systems: Organizing Views

1. LinearLayout

Definition: Arranges child views in a single direction (horizontal or vertical). Attributes:

  • android:orientation: horizontal or vertical.
  • android:layout_weight: Distributes extra space proportionally.

Example: Vertical LinearLayout

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button android:text="Button 1"/>
    <Button android:text="Button 2"/>
</LinearLayout>

Visual (State After Inflation):

graph LR
    A["LinearLayout (Vertical)"] --> B["Button 1"]
    A --> C["Button 2"]

Advantages/Disadvantages:

Pros Cons
Simple to use Nested layouts can hurt performance
Good for basic layouts Limited flexibility

2. RelativeLayout

Definition: Positions child views relative to each other or the parent. Key Attributes:

  • android:layout_above, android:layout_below
  • android:layout_toLeftOf, android:layout_toRightOf
  • android:layout_alignParentTop

Example: RelativeLayout for a Login Form

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp"/>

    <Button
        android:id="@+id/loginButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/username"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

Visual (State After Inflation):

graph TD
    A["RelativeLayout"] --> B["EditText (username)"]
    A --> C["Button (loginButton)"]
    B -->|"layout_below"| C

Advantages/Disadvantages:

Pros Cons
Flexible positioning Harder to maintain for complex UIs
No nesting needed Performance issues with many views

3. ConstraintLayout (Modern Alternative)

Definition: Uses constraints (rules) to position views relative to each other, parent, or screen edges. Most efficient for complex layouts.

Example: ConstraintLayout for a Dashboard

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dashboard"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Visual (State After Inflation):

graph LR
    A["ConstraintLayout"] --> B["TextView (title)"]
    A --> C["Button (button1)"]
    B -->|"constraintTop_toTopOf"| A
    B -->|"constraintStart_toStartOf"| A
    C -->|"constraintTop_toBottomOf"| B

Advantages/Disadvantages:

Pros Cons
High performance (flat hierarchy) Steeper learning curve
Supports complex layouts XML can get verbose

XML-Based UI Design

Key Components:

  1. Attributes:

    • android:layout_width: match_parent, wrap_content, or fixed dp.
    • android:layout_height: Same as above.
    • android:padding: Space inside the view.
    • android:margin: Space outside the view.
  2. Styles and Themes:

    • Styles: Reusable sets of attributes (defined in res/values/styles.xml).
      <style name="MyButtonStyle" parent="Widget.AppCompat.Button">
          <item name="android:textColor">#FFFFFF</item>
          <item name="android:background">@color/colorPrimary</item>
      </style>
      
    • Themes: Global styles applied to the entire app (defined in res/values/themes.xml).

Example: Applying a Style

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Styled Button"
    style="@style/MyButtonStyle"/>

Adaptive and Responsive Layouts

Definition: Layouts that adapt to different screen sizes, orientations, and densities.

Techniques:

  1. Density Independence (dp vs. px):

    • Use dp (density-independent pixels) instead of px (pixels).
    • Example: android:layout_width="100dp" scales across devices.
  2. Alternative Layouts:

    • Provide different layouts in res/layout-land/ (landscape) and res/layout-port/ (portrait).
    • Example:
      res/
      ├── layout/          # Default (portrait)
      │   └── activity_main.xml
      └── layout-land/     # Landscape
          └── activity_main.xml
      
  3. ConstraintLayout Chains:

    • Use app:layout_constraintHorizontal_chainStyle or app:layout_constraintVertical_chainStyle to handle dynamic spacing.

Example: Adaptive Button Sizing

<Button
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Adaptive Button"
    app:layout_constraintWidth_percent="0.5"/>

Visual: Screen Size Adaptation

graph TD
    A["Small Screen (Portrait)"] --> B["LinearLayout (Vertical)"]
    C["Large Screen (Landscape)"] --> D["ConstraintLayout with Chains"]

In the Real World

  1. eSewa App (Nepal):

    • Uses ConstraintLayout for its adaptive payment form, ensuring buttons and fields resize correctly on all devices (from low-end phones to tablets).
    • Why? eSewa’s user base includes diverse devices, and a responsive UI reduces bounce rates.
  2. Pathao Rider App:

    • Employs RelativeLayout for dynamic ride request buttons that reposition based on the rider’s current location marker (a MapView).
    • How? The "Accept Ride" button is constrained to appear near the user’s live location pin, improving usability.
  3. Daraz Mobile App (Nepal):

    • Uses ConstraintLayout chains to create a scrollable product grid that adjusts column count based on screen width (e.g., 2 columns on small phones, 3 on tablets).
    • Impact: Faster loading and better readability for product listings.
  4. Ncell Recharge App:

    • Implements alternative layouts (layout-port vs. layout-land) to switch between a vertical menu (portrait) and a horizontal tab bar (landscape) for recharge options.
    • Result: Users don’t need to scroll horizontally on larger screens, reducing errors.

Worked Example: Building a Login Screen

Requirements:

  • Username and password fields.
  • Login button centered below the fields.
  • Adaptive to portrait/landscape.

Solution (ConstraintLayout):

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/username"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Username"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_percent="0.9"/>

    <EditText
        android:id="@+id/password"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="Password"
        android:inputType="textPassword"
        app:layout_constraintTop_toBottomOf="@id/username"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_percent="0.9"/>

    <Button
        android:id="@+id/loginButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Login"
        app:layout_constraintTop_toBottomOf="@id/password"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_percent="0.5"
        app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Visual: State After Inflation (Portrait)

graph LR
    A["ConstraintLayout"] --> B["EditText (username)"]
    A --> C["EditText (password)"]
    A --> D["Button (loginButton)"]
    B -->|"constraintTop_toTopOf"| A
    C -->|"constraintTop_toBottomOf"| B
    D -->|"constraintTop_toBottomOf"| C

Trace for Landscape Orientation:

Step Action Result
1 Load layout-land/activity_login.xml Uses same constraints but repositions button horizontally centered.
2 Apply app:layout_constraintWidth_percent="0.3" Button width reduces to 30% of screen.
3 Recalculate constraints Fields stack vertically; button stays centered below them.

Common Pitfalls and Best Practices

Pitfalls:

  1. Nested LinearLayouts:

    • Causes performance overhead due to multiple view traversals.
    • Fix: Use ConstraintLayout or flatten hierarchy.
  2. Hardcoded Dimensions:

    • Layouts break on different screen sizes.
    • Fix: Use dp, wrap_content, match_parent, or ConstraintLayout chains.
  3. Ignoring Lifecycle:

    • Views may not redraw after orientation changes.
    • Fix: Use configChanges in AndroidManifest.xml or save/restore state in onSaveInstanceState.

Best Practices:

  1. Reuse Styles/Themes:
    • Define colors, fonts, and padding once in styles.xml.
  2. Use ConstraintLayout for Complex UIs:
    • Reduces nesting and improves performance.
  3. Test on Multiple Devices:
    • Use Android Studio’s Layout Inspector to preview layouts.
  4. Optimize for Touch:
    • Ensure buttons and interactive elements are at least 48x48 dp.

Exam Tip

How This Unit is Examined:

  1. Short Questions (2-5 marks):

    • Define View, Widget, and ViewGroup.
    • Differences between LinearLayout, RelativeLayout, and ConstraintLayout.
    • Purpose of dp vs. px.
  2. Programming Questions (10-15 marks):

    • Write XML for a given layout (e.g., "Create a layout with 3 buttons in a row using LinearLayout").
    • Debug a broken layout (e.g., "Why isn’t this Button appearing?").
    • Explain how to make a layout adaptive for different screen sizes.
  3. Scenario-Based (10-20 marks):

    • Design a UI for a specific app (e.g., "Create a UI for a food delivery app’s order confirmation screen").
    • Justify your choice of layout (e.g., "Why did you use ConstraintLayout instead of RelativeLayout?").

Key Focus Areas for Exams:

  • XML Attributes: Know layout_width, layout_height, margin, padding, and constraint-specific attributes.
  • Layout Hierarchy: Understand parent-child relationships and how they affect rendering.
  • Adaptive Design: Be able to describe how to handle orientation changes and screen sizes.
  • Performance: Recognize when to avoid nested layouts.

Common Exam Questions:

  1. "Explain the difference between match_parent and wrap_content with examples."
  2. "How would you design a responsive layout for a chat app that works on both phones and tablets?"
  3. "Write the XML for a ConstraintLayout that positions a TextView at the top-center and a Button below it, centered horizontally."
  4. "What are the advantages of using ConstraintLayout over RelativeLayout in modern Android development?"

Based on the TU BIM syllabus for Mobile Application Development (IT272), unit 4.

Discussion

Loading…