Layouts are where you define the view of your application using builtin Android views, view groups, and/or your own custom views based on them. These XML files live in your res/
directory.
Writing layouts this way allows us to decouple the presentation layer from business logic.
Although you could write all your views in Java, that makes it a lot harder to leverage the full power of resource system. Plus it often becomes a maintenance issue.
activity_loosely_coupled.xml
There is always one parent at the root of the layout and the layout may contain many views.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<!--Welcome string-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/WELCOME_TEXT"
style="@style/Text"/>
...
<LinearLayout/>
There are many prebuilt items that you can use, including Button
, TextView
, ImageView
, grids, and more!
You give each view an id so that you can wire up to logic in the Java class that points to this view. The system generates an R.java
file behind the scenes that maps your resources and views to a Java-accessible construct. This is generated at compile time, but the decision of which view to show is determined at runtime.
Note: Sometimes the
R.java
files gets out of sync with your views and resources. This often happens if you change a lot in a small amount of time. If you start seeing weird class cast exceptions, then this may be your culprit.
In this example, the view activity_button
is defined in activity_loosely_coupled.xml
with an id:
<!--Activity button-->
<Button
android:id="@+id/activity_button"
android:text="@string/ACTIVITY_BUTTON_TEXT"
style="@style/Button"/>
In the activity, you use setContentView()
to specify which layout to use and Android brings it to life. After that, you can access its subviews with the id you gave it in the XML file.
findViewById( R.id.activity_button ).setOnClickListener( new View.OnClickListener()
{
@Override
public void onClick( View v )
{
startActivity( createViewSystemIntent() );
}
};
}
In this example layout we can make the activity button do something by referencing it in onCreate()
. Here we attach a click listener that will open another activity.
You can change all manner of information about the views. Good examples are setting the text or colors to display, animating views, and/or attaching user actions.
The XML gets turned into Java components at runtime when the Android system "inflates" the view.
As shown above, with an Activity
the inflation occurs in the lifecycle method onCreate()
with the setContentView()
function.
It's a little different in Fragment
's because the inflation occurs in the lifecycle method onCreateView()
by using the inflate()
function.
When views are inflated, they are added to the view hierarchy. Any time that you add subviews or view groups, you are deepening the hierarchy tree that represents your views. You can use the Hierarchy Viewer tool to optimize views that are loading slowly.
All of the view components are Java classes, which means they can be extended!
You can add custom behavior when a builtin components provide some, though not all of the behavior you'd like. You can also create custom views that are collections of the basic view types.
For example, say you wanted to create a date and time clock. You could create a view that combines a TextView
for the date and and image or other control to show an analog version of the time).
These views are only limited by your imagination! We won't be covering them in depth in this class, but there's an excellent presentation by Chiu-Ki Chan: Custom Components.