ZOFTINO.COM android and web dev tutorials

Android Resources Tutorial

Every application contains code and resources. While code provides behavior of applications, resources are static which either provide configuration information to behavior or are displayed in UI. Examples of application resources are images, text values, xml, audio and video files, fonts, color definitions, menus, animation, and user interface layouts.

Android Resources

Android application’s code is kept under java folder and resources are saved under res folder as shown in below picture. Keeping resources separate from code makes it easy to maintain and enhance applications.

android resources

Below are resource folders which are under res folder and are used to include various resources in android app.

Accessing Resources

For each and every resource added to res folder, compiler generates resource ids using which you can access the resources in application. Compiler creates R class which contains all resource ids. You can access resource from code and xml.

Below example shows accessing a resource in code.

 Toast.makeText(this,
        getResources().getString(R.string.login_fail),
        Toast.LENGTH_SHORT).show();

Below example shows accessing a resource in xml

 <TextView
    android:id="@+id/coupon_hd"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    . . .
    android:text="@string/coupon_head"
    />
 

Accessing android platform resources.

Animation imgAnimationIn =  AnimationUtils.
loadAnimation(this,   android.R.anim.slide_in_left);

imageSwitcher.setInAnimation(imgAnimationIn);

Using Resource object, which can be obtained by calling getResources() method in activity, you can load resources in code using various methods such as getColor, getColorStateList, getDimension, getDrawable, getFont, getLayout, getInteger, getString, openRawResource, ..etc.

Drawable d = getResources().getDrawable(R.drawable.national_animal, null);
((ImageView)findViewById(R.id.img)).setImageDrawable(d);

Below example shows how to access an attribute of current theme from xml.

<Button
    android:id="@+id/submit_tv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    . . .
    android:elevation="?android:elevation"/>

Alternate Resources

Android supports variants of resources described above for different device configurations. You can provide alternate resources for different screen sizes, for different languages, for different orientations, ..etc. At runtime, android picks the right resources based on the device configuration.

Resource folders described in the above section are default resource folders. Depending on the type of alternate resource that you want to create, you need to add -<qualifier> to the default resource folder names.

For example to provide different user interface for different screen sizes, you need to create separate layout xml file for default, large and extra large screens and save them in layout, layout-large and layout-xlarge folders respectively. Folder name contains large and xlarge, these are qualifiers and android uses them to indentify resource folder based on device configuration.

Below are some widely used resource variants and its qualifers.

  • Screen size : For different device screen sizes, different resources such as drawables, layouts, .. etc. can be created to provide different UI experience to users. Folder name qualifiers are small, normal, large and xlarge.
  • Screen orientation : Alternate resources can be provided for portrait and landscape orientations. Folder name qualifiers are port and land.
  • Android versions : Alternate resources can be used for different android versions. Folder name qualifiers are v19, v21, v24, v26 ..etc.
  • Screen pixel density : For different screen pixel densities, you can provide different resource so that android picks the right resource based on the device screen density. Folder name qualifiers are ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi, nodpi, tvdpi, anydpi and nnndpi.
  • Languages : You can create different resources for different languages so that android picks the right resource based on device locale. Example folder qualifier name are b+en-US, b+hi-IN, b+ja-JE, ..etc.
  • Different resources can be provided for different mobile country codes (MCC) and mobile network cods (MNC) so that app can be made to display resources based on the country to which mobile number belongs to or based on carrier of mobile network the device connected to.
  • You can provide different resources for layout-direction-right-to-left and layout-direction-left-to-right. Folder qualifier names are ldrtl and ldltr.

Please see alternate resources for complete list of alternate resources and for order of precedence given to them when android tries to match a resource based on current device configuration.

Remote Config

Resources saved under res folder are part of APK and will be on user device after app is installed. If you want to change resources, you will have to release new version of your app containing changed resources. The resource changes will be available to user only after they upgrade your app.

To prevent frequent releases for configuration changes, you can use Firebase remote config which allows you to change values for configuration parameters and make them available to app without releasing new version and upgrading it.

Android Alternate Resources Example

Below example shows how to create alternate resources for device orientation. Two separate layouts of registration screen for portrait and landscape are created and saved in layouts and layouts-land respectively.

Portrait output

android alternate resources example

Landscape output

android resources example

Default Layout

<?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"
    android:layout_margin="8dp">
    <android.support.design.widget.TextInputLayout
        android:id="@+id/name_l"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp">
        <EditText
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Name"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/address_l"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp">
        <EditText
            android:id="@+id/address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Address"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/city_l"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp">
        <EditText
            android:id="@+id/city"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="City"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/phone_l"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp">
        <EditText
            android:id="@+id/phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Phone"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/email_l"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp">
        <EditText
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Email"/>
    </android.support.design.widget.TextInputLayout>
    <Button
        android:id="@+id/submit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        style="@style/Widget.AppCompat.Button.Colored"
        android:text="Submit"/>
</LinearLayout>

Landscape Layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    android:layout_margin="8dp">
    <android.support.design.widget.TextInputLayout
        android:id="@+id/name_l"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/address_l"
        app:layout_constraintTop_toBottomOf="parent">
        <EditText
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Name"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/address_l"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toRightOf="@+id/name_l"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="parent">
        <EditText
            android:id="@+id/address"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Address"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/city_l"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/state_l"
        app:layout_constraintTop_toBottomOf="@+id/name_l">
        <EditText
            android:id="@+id/city"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="City"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/state_l"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toRightOf="@+id/city_l"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/name_l">
        <EditText
            android:id="@+id/state"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="State"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/phone_l"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/email_l"
        app:layout_constraintTop_toBottomOf="@+id/city_l">
        <EditText
            android:id="@+id/phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Phone"/>
    </android.support.design.widget.TextInputLayout>
    <android.support.design.widget.TextInputLayout
        android:id="@+id/email_l"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toRightOf="@+id/phone_l"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/city_l">
        <EditText
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:hint="Email"/>
    </android.support.design.widget.TextInputLayout>

    <Button
        android:id="@+id/submit"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        style="@style/Widget.AppCompat.Button.Colored"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/email_l"
        android:text="Submit"/>

</android.support.constraint.ConstraintLayout>

Activity

public class AlternateResourceActivity extends AppCompatActivity {
    private static final String TAG = "AlternateResourceA";

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