Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Android UI Components, Activity Lifecycle, and Data Persistence

Tech May 14 1

LinearLayout and RelativeLayout

Android provides two primary layout managers for structuring user interfaces: LinearLayout and RelativeLayout. Their most common configuration attributes are listed below.

LinearLayout

LinearLayout aligns children in a single direction—vertical or horizontal—using the android:orientation flag. The table summarizes several frequently used attributes.

Attribute Description
android:id Unique identifire
android:layout_width Width
android:layout_height Height
android:layout_margin Outer spacing
android:layout_padding Inner spacing
android:orientation vertical or horizontal
android:background Background

The following layout demonstrates spacing and weight distribution:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/top_panel"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:orientation="vertical"
        android:background="#000000"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingTop="50dp"
        android:paddingBottom="10dp"
        android:layout_marginBottom="20dp">
        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#FF0033"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="#0066FF"
        android:orientation="horizontal"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp">
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:background="#000000"
            android:layout_weight="1"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:background="#FF0033"
            android:layout_weight="2"/>
        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:background="#55AA99"
            android:layout_weight="2"/>
    </LinearLayout>
</LinearLayout>

RelativeLayout

RelativeLayout positions children relative to siblings or the parent boundaries. The following table highlights positioning attributes beyond those shared with LinearLayout.

Attribute Description
android:layout_toLeftOf Left of target view
android:layout_toRightOf Right of target view
android:layout_alignBottom Align bottom with target
android:layout_alignParentBottom Align with parent bottom
android:layout_below Below target view
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/block_a"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#000000" />

    <View
        android:id="@+id/block_b"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_below="@id/block_a"
        android:background="#FF0033" />

    <LinearLayout
        android:id="@+id/row_container"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_below="@id/block_b"
        android:orientation="horizontal"
        android:background="#0066FF"
        android:padding="15dp">
        <View
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:background="#FF0033"/>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#000000"
            android:padding="15dp">
            <View
                android:id="@+id/left_block"
                android:layout_width="100dp"
                android:layout_height="match_parent"
                android:background="#FF9900" />
            <View
                android:id="@+id/right_block"
                android:layout_width="100dp"
                android:layout_height="match_parent"
                android:layout_toRightOf="@id/left_block"
                android:layout_marginLeft="10dp"
                android:background="#FF9900" />
        </RelativeLayout>
    </LinearLayout>
</RelativeLayout>

Interactive UI Widgets

TextView

Text can be styled with size, color, ellipsize behavior, icons, and decorations such as strikethrough or underline. A marquee effect requires singleLine and ellipsize="marquee" with focusability enabled. The Java snippet below applies programmatic formatting:

public class TextStylingActivity extends AppCompatActivity {
    private TextView strikeView;
    private TextView underlineView;
    private TextView marqueeView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_text_styling);

        strikeView = findViewById(R.id.tv_strike);
        strikeView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
        strikeView.getPaint().setAntiAlias(true);

        underlineView = findViewById(R.id.tv_underline);
        underlineView.getPaint().setFlags(Paint.UNDERLINE_TEXT_FLAG);

        marqueeView = findViewById(R.id.tv_marquee);
        marqueeView.setSelected(true);
    }
}

Button

Custom backgrounds defined in drawable resources can manage corner radius and press feedback. Click handling occurs via programmatic OnClickListener or the onClick XML attribute.

<Button
    android:id="@+id/btn_rounded"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:text="Action"
    android:textSize="20sp"
    android:textColor="#FFFFFF"
    android:background="@drawable/bg_rounded_button"
    android:onClick="onButtonPressed"/>

Listener assignment inside Activity:

Button actionBtn = findViewById(R.id.btn_rounded);
actionBtn.setOnClickListener(v -> {
    Toast.makeText(this, "Pressed", Toast.LENGTH_SHORT).show();
    startActivity(new Intent(this, TargetScreen.class));
});

EditText, RadioButton, CheckBox

Each widget offers standard attributes plus custom drawable for checked states. Event listeners such as OnCheckedChangeListener handle selection:

CheckBox checkBox = findViewById(R.id.cb_custom);
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
    String message = isChecked ? "Checked" : "Unchecked";
    Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
});

ImageView

Scale type constants control image fitting: fitCenter preserves ratio, centerCrop fills bounds and crops excess, and fitXY stretches to fill regardless of ratio. Third‑party libraries like Glide simplify network image loading:

Glide.with(context).load("https://example.com/image.png").into(imageView);

ListView and RecyclerView

ListView

ListView relies on an adapter, often a custom BaseAdapter, to supply rows. View recycling improves performance.

Adapter implementation with view holder pattern:

public class ArticleAdapter extends BaseAdapter {
    private final Context context;
    private final LayoutInflater inflater;

    public ArticleAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() { return 10; }

    @Override
    public Object getItem(int position) { return null; }

    @Override
    public long getItemId(int position) { return 0; }

    static class RowHolder {
        ImageView thumbnail;
        TextView title;
        TextView date;
        TextView summary;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        RowHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.row_article, parent, false);
            holder = new RowHolder();
            holder.thumbnail = convertView.findViewById(R.id.iv_thumb);
            holder.title = convertView.findViewById(R.id.tv_title);
            holder.date = convertView.findViewById(R.id.tv_date);
            holder.summary = convertView.findViewById(R.id.tv_summary);
            convertView.setTag(holder);
        } else {
            holder = (RowHolder) convertView.getTag();
        }
        holder.title.setText("Sample Title");
        holder.date.setText("2088-08-08");
        holder.summary.setText("Brief description...");
        Glide.with(context).load("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png").into(holder.thumbnail);
        return convertView;
    }
}

Item click handling:

listView.setOnItemClickListener((parent, view, position, id) -> {
    Toast.makeText(this, "Position: " + position, Toast.LENGTH_SHORT).show();
});
listView.setOnItemLongClickListener((parent, view, position, id) -> {
    Toast.makeText(this, "Long press: " + position, Toast.LENGTH_SHORT).show();
    return true;
});

RecyclerView

RecyclerView offers improved flexibility for lists, grids, and staggered layouts. Different ViewHolder subtypes can coexist within the same adapter. The XRecyclerView library extends it with header, footer, pull‑to‑refresh, and infinite scroll.

ScrollView and HorizontalScrollView

ScrollView permits vertical scrolling of a single child, while HorizontalScrollView enables horizontal scrolling. The following layout stacks buttons vertically and adds a horizontally scrollable row:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

        <Button
            android:id="@+id/btn_textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="TextView"/>

        <Button
            android:id="@+id/btn_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Button"/>

        <HorizontalScrollView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <Button
                    android:layout_width="200dp"
                    android:layout_height="300dp"
                    android:text="Item A"/>
                <Button
                    android:layout_width="200dp"
                    android:layout_height="300dp"
                    android:text="Item B"/>
            </LinearLayout>
        </HorizontalScrollView>
    </LinearLayout>
</ScrollView>

WebView

WebView loads remote URLs, local assets, or raw HTML. Navigation history is controlled with goBack() and goForward().

WebView browser = findViewById(R.id.web_view);
browser.getSettings().setJavaScriptEnabled(true);
browser.loadUrl("https://example.com");

Override back press for in‑page navigation:

@Override
public void onBackPressed() {
    if (browser.canGoBack()) {
        browser.goBack();
    } else {
        super.onBackPressed();
    }
}

Overlay and Dialog Components

Toast

A custom Toast can include a layout graph or reposition itself:

Toast toast = Toast.makeText(context, "Saved", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 100);
toast.show();

AlertDialog

AlertDialog supports single‑choice, multi‑choice, and custom view layouts.

ProgressBar and ProgressDialog

Indeterminate progress indicators can use custom drawables:

<ProgressBar
    android:id="@+id/custom_progress"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/MyProgressBar"/>

Custom Dialog

Create a style extending Theme.AppCompat.Light.Dialog and inflate a custom layout.

PopupWindow

PopupWindow displays anchored floating content; its appearance and position are controlled programmatically.

Activity Lifecycle and Navigation

Lifecycle Callbacks

The essential lifecycle sequence includes onCreate, onStart, onResume, onPause, onStop, onRestart, and onDestroy. Transitions like backgrounding invoke onPause and onStop; returning triggers onRestart, onStart, and onResume.

Explicit and Implicit Intents

Explicit navigation targets a concrete Activity class; implicit intents match action and category filters.

Intent explicit = new Intent(this, ProfileActivity.class);
explicit.putExtra("user_id", 42);
startActivity(explicit);

Result‑oriented launches utilise ActivityResultLauncher with the Activity Result API.

Launch Modes

Configure the android:launchMode attribute to one of the following:

  • standard – new instance every time.
  • singleTop – reuse existing top instance; onNewIntent delivered.
  • singleTask – clear activities above the target in the same task.
  • singleInstance – isolated single instance in its own task.

Fragments

Fragments possess their own lifecycle and rely on a host Activity. Communication occurs via interfaces or direct method calls through getActivity().

When replacing Fragments, using hide() instead of replace() presevres view state upon back navigation.

Fragment current = getParentFragmentManager().findFragmentByTag("root_fragment");
if (current != null) {
    getParentFragmentManager().beginTransaction()
        .hide(current)
        .add(R.id.container, new DetailFragment())
        .addToBackStack(null)
        .commit();
}

Event Handling

Listener‑Based

Common listener interfaces include OnClickListener and OnTouchListener. When multiple listeners of the same type are set, the latest overwrites previous ones.

Callback‑Based

Touch events propagate from the view’s own onTouchEvent to the Activity’s method unless consumed earlier.

View Event Dispatching

dispatchTouchEvent checks OnTouchListener first; if it returns false, onTouchEvent processes the event and may trigger onClick or onLongClick.

Handler

Handler schedules future work and enables cross‑thread communication.

Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.postDelayed(() -> {
    navigateToHome();
}, 3000);

new Thread(() -> {
    Message msg = Message.obtain();
    msg.what = 101;
    uiHandler.sendMessage(msg);
}).start();

Property Animation

Property animations modify actual object attributes. ObjectAnimator targets translation, alpha, rotation, or scale.

ObjectAnimator mover = ObjectAnimator.ofFloat(targetView, "translationY", 0f, 500f, 200f, 800f);
mover.setDuration(2000);
mover.start();

Local Data Storage

SharedPreferences

Lightweight key‑value pairs stored in XML.

SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("user_token", token);
editor.apply();

String storedToken = prefs.getString("user_token", "");

Files reside under /data/data/<package>/shared_prefs/.

Internal File Storage

Read and write through FileInputStream/FileOutputStream using openFileInput and openFileOutput:

private void persistPayload(String payload, String filename) {
    try (FileOutputStream fos = openFileOutput(filename, MODE_PRIVATE)) {
        fos.write(payload.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private String readPayload(String filename) {
    StringBuilder builder = new StringBuilder();
    try (FileInputStream fis = openFileInput(filename)) {
        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer)) > 0) {
            builder.append(new String(buffer, 0, length));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return builder.toString();
}

External File Storage

On modern Android versions, app‑specific external directories are accessed via getExternalFilesDir(null):

String basePath = getExternalFilesDir(null).getAbsolutePath();
File dir = new File(basePath, "uploads");
if (!dir.exists()) dir.mkdirs();
File file = new File(dir, "log.txt");
// stream operations accordingly

Local Broadcasts

LocalBroadcastManager confines broadcasts within the app. Register a dynamic receiver and unregister in onDestroy.

BroadcastReceiver refreshReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if ("com.internal.REFRESH".equals(intent.getAction())) {
            updateContent();
        }
    }
};

LocalBroadcastManager.getInstance(this)
    .registerReceiver(refreshReceiver, new IntentFilter("com.internal.REFRESH"));

// Sending side
Intent intent = new Intent("com.internal.REFRESH");
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

Ripple Effect on Custom Shapes

Rounded views can incorporate material ripple with a <ripple> drawable:

<!-- ripple_rounded.xml -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#22000000">
    <item android:drawable="@drawable/shape_rounded_green" />
</ripple>
<TextView
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="@drawable/ripple_rounded"
    android:elevation="8dp"
    android:gravity="center"
    android:text="Sign In"
    android:textColor="@android:color/white"
    android:textSize="18sp" />

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.