Managing Unified Activity Layouts
To enforce a consistent UI structure while allowing specific content differentiation, extend the standard activity class to manage common views. This strategy centralizes toolbar handling and placeholder definitions.
Layout Skeleton
Define a base XML resource containing the global structure. It should include an inclusion for shared components like headers and a container frame for dynamic inflation of child layouts.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/include_top_section" />
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<!-- Error state indicator -->
<ViewStub
android:id="@+id/stub_failure_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout="@layout/layout_error_display" />
<!-- Loading state indicator -->
<ViewStub
android:id="@+id/stub_loading_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout="@layout/layout_progress_spinner" />
</FrameLayout>
</LinearLayout>
Core Implementation
The parent class loads this base template and uses LayoutInflater to place the derived layout into the designated slot. Child activities declare their specific resources via an abstract method.
public abstract class BaseAppActivity extends AppCompatActivity {
/**
* Define the resource ID for the unique activity layout
*/
protected abstract int getChildLayoutId();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_template);
ViewGroup targetContainer = findViewById(R.id.content_frame);
LayoutInflater inflater = LayoutInflater.from(this);
// Inflate child layout into the container
inflater.inflate(getChildLayoutId(), targetContainer, true);
}
}
Implementations only need to return the layout resource ID, ensuring the framework handles the injection logic.
Accessing Custom Drawable Attributes
Certain input fields require programmatic access to attached drawables to handle interacsions like clearing text or triggering actions.
Configuration in XML
Extend EditText and specify the drawable resource to align to the end or right side of the input box.
<com.app.widgets.SearchInputWidget
android:id="@+id/query_input_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Type search keyword here"
android:textColor="#424242"
app:drawableEnd="@drawable/ic_action_search" />
Retrieving the Graphic Asset
Within the custom view implementation, retrieve the compound drawable array. The index corresponds to the posision relative to the input area (Left, Top, Right/End, Bottom).
public class SearchInputWidget extends EditText {
private Drawable mRightAsset;
public SearchInputWidget(Context context, AttributeSet attrs) {
super(context, attrs);
bindDrawableResources();
}
private void bindDrawableResources() {
// getCompoundDrawables returns [left, top, right, bottom]
Drawable[] original = getCompoundDrawables();
if (original.length > 2) {
mRightAsset = original[2];
}
}
// Logic to utilize mRightAsset, e.g., setting a click listener
public void clearText() {
setText("");
}
}
This pattern allows reusable components to react to their internal graphical elements without relying solely on static configurations.