Bekerja dengan Toolbar di Android

Bagus Aji Santoso 16 Oktober 2017

Bekerja dengan Toolbar di Android

Pendahuluan

Toolbar diperkenalkan saat Android Lollipop, API 21 dirilis dan merupakan penerus dari ActionBar. Toolbar adalah sebuah ViewGroup yang dapat diletakkan di mana saja di dalam layout XML kita. Tampilan dan kelakuannya dapat diatur dengan lebih mudah dibanding ActionBar.

img

Toolbar dapat bekerja dengan sangat baik untuk aplikasi yang menargetkan API 21 ke atas. Meskipun begitu, Android telah memperbarui pustaka AppCompat agar Toolbar dapat dipakai di perangkat dengan sistem operasi Android yang lebih lama. Di AppCompat, Toolbar diimplementasi di dalam kelas android.support.v7.widget.Toolbar .

Ada dua cara untuk menggunakan Toolbar:

  1. Gunakan sebuah Toolbar sebagai Action Bar untuk mendapatkan fasilitas ActionBar yang sudah ada (seperti pembacaan dan pemilihan menu, ActionBarDrawerToggle, dll.) namun ingin bisa mengatur bagaimana penampilannya.
  2. Menggunakan Toolbar untuk situasi dimana Action Bar sudah tidak mampu lagi menanganinya, contoh saat ingin menampilkan beberapa toolbar di dalam layar, dll.

Memahami App Resource di Android

Toolbar vs ActionBar

Toolbar adalah generalisasi dari sistem ActionBar. Perbedaan yang membedakan antara Toolbar dari ActionBar adalah:

  • Toolbar adalah sebuah View yang memiliki sebuah komponen layout seperti View lainnya.
  • Karena sebuah View, posisi, animasi serta kontrol toolbar dapat diatur dengan lebih mudah.
  • Bisa membuat beberapa elemen Toolbar di satu activity.

Perlu diingin kita juga dapat mengatur Toolbar manapun sebagai ActionBar-nya Activity, artinya kita mendapatkan options menu didalamnya.

Catat juga bahwa ActionBar masih bisa dipakai jika hanya membutuhkan sebuah bar statis di atas yang dapat memiliki ikon dan tombol back.

Menggunakan Toolbar sebagai ActionBar

Untuk menggunakan Toolbar sebagai ActionBar, pertama pastikan AppCompat-v7 support library ditambahkan ke build.gradle(Module:app):

dependencies {
  ...
  compile 'com.android.support:appcompat-v7:25.2.0'
}

Lalu, disable ActionBar yang ada di res/values/styles.xml. Cara termudah ialah dengan meng-extend Theme.AppCompat.NoActionBar (atau bariasi Light-nya):

<resources>
  <!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  </style>
</resources>

Sekarang kita perlu menambah sebuah Toolbar ke layout Activity. Kelebihan utamanya kita bisa memposisikannya dimanapun di dalam layout. Di bawah ini kita meletakkan toolbar di bagian paling atas sebuah LinearLayout seperti ActionBar pada umumnya:

<LinearLayout 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:fitsSystemWindows="true"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:minHeight="?attr/actionBarSize"  
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:titleTextColor="@android:color/white"
      android:background="?attr/colorPrimary">
    </android.support.v7.widget.Toolbar>

    <!-- Layout for content is here. This can be a RelativeLayout  -->

</LinearLayout>

Catatan: Pembaca mungkin ingin menambahkan android:fitsSystemWindows="true" (learn more) ke parent layout dari Toolbar untuk memastikan bahwa tinggi activity dihitung dengan benar.

Karena Toolbar hanyalah sebuah ViewGroup ia dapat di berikan style dan diposisikan seperti view lain. Artinya, jika menggunakan RelativeLayout, kita harus memastikan semua view lain berada di bawah toolbar secara eksplisit.

Menggunakan ActionBar di Android

Selanjutnya, di dalam Activity atau Fragment, atur Toolbar agar bekerja seperti ActionBar dengan memanggil method setSupportActionBar(ToolBar):

Catatan: Saat menggunakan support library, pastikan bahwa pembaca mengimpor android.support.v7.widget.Toolbar bukan android.widget.Toolbar.

import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;

public class MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        // Find the toolbar view inside the activity layout
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        // Sets the Toolbar to act as the ActionBar for this Activity window.
        // Make sure the toolbar exists in the activity and is not null
        setSupportActionBar(toolbar);
    }

    // Menu icons are inflated just as they were with actionbar
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
}

Kemudian, kita perlu memastikan bahwa sebuah resource file menu dibaca di dalam onCreateOptionsMenu:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/miCompose"
        android:icon="@drawable/ic_compose"
        app:showAsAction="ifRoom"
        android:title="Compose">
    </item>
    <item
        android:id="@+id/miProfile"
        android:icon="@drawable/ic_profile"
        app:showAsAction="ifRoom|withText"
        android:title="Profile">
    </item>
</menu>

Untuk melakukan click handling pada Toolbar, silahkan baca juga artikel tentang ActionBar.

img

Sampai di sini, semua item menu akan ditampilkan di Toolbar, lewat callback menu standar.

Penggunaan Ulang Toolbar

Kita dapat menggunakan elemen Toolbar yang sama di beberapa layout menggunakan tag include. Pertama, buat dulu Toolbar-nya di res/layout/toolbar_main.xml:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"/>

Lalu, kita dapat memanggilnya dengan tag <include /> di layout activity:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <!-- Load the toolbar here -->
    <include
        layout="@layout/toolbar_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/> 

    <!-- Rest of content for the activity -->

</LinearLayout>

Dengan demikian kita akan memiliki navigasi yang konsisten antar activity atau peruabhan konfigurasi.

Memberi Style Untuk Toolbar

Tampilan Toolbar diatur dengan berbagai cara diantaranya menggunakan android:theme, app:titleTextAppearance, dan app:popupTheme. Contoh:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="?attr/actionBarSize"  
    android:background="?attr/colorPrimary"
    android:theme="@style/ToolbarTheme"
    app:titleTextAppearance="@style/Toolbar.TitleText"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/>

Kemudian, kita perlu membuat style baru di res/values/styles.xml:

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/colorPrimary</item>
  <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="ToolbarTheme" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
  <!-- android:textColorPrimary adalah warna teks title yang ada di Toolbar  -->
  <item name="android:textColorPrimary">@android:color/holo_blue_light</item>
  <!-- actionMenuTextColor adalah warna teks action (menu item)  -->
  <item name="actionMenuTextColor">@android:color/holo_green_light</item>
  <!-- Memberi warna accent untuk input field seperti checkbox -->
  <item name="colorAccent">@color/cursorAccent</item>
  <!-- memberi warna view saat normal. -->
  <item name="colorControlNormal">@color/controlNormal</item>
  <!-- Memberi warna saat view aktif (sedang diberi tanda cek atau di switch) -->
  <item name="colorControlActivated">@color/controlActivated</item>
  <!-- Memberi warna kontrol untuk efek ripples atau pemilihan list -->
  <item name="colorControlHighlight">@color/controlActivated</item>

  <!-- Tambahkan jika ingin memberi efek ripple saat memilih salah satu ikon -->
  <!-- 
  <item name="selectableItemBackground">?android:selectableItemBackground</item>
  <item name="selectableItemBackgroundBorderless">?android:selectableItemBackground</item> 
  -->
</style>

<!-- Mengatur style title yang ada di dalam Toolbar -->
<style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
    <item name="android:textSize">21sp</item>
    <item name="android:textStyle">italic</item>
</style>

Hasilnya sebagai berikut:

img

Displaying an App Icon

Dalam beberapa kasus, kita mungkin ingin menampilkan sebuah ikon aplikasi di dalam Toolbar. Kita dapat melakukannya dengan menambahkan kode berikut ke dalam Activity:

// Membaca view Toolbar yang ada di XML dan mengaturnya sebagai ActionBar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

// Menampilkan ikon di Toolbar
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);

Selanjutnya, kita perlu menghapus left inset margin yang membuat posisi ikon terlalu kiri dengan menambahkan app:contentInsetStart:

<android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      app:contentInsetLeft="0dp"
      app:contentInsetStart="0dp"
      ...
      >
</android.support.v7.widget.Toolbar>

Dengan demikian ikon di atas seharusnya sudah dapat tampil di dalam Toolbar sesuai yang diinginkan.

Custom Title View

Sebuah Toolbar hanyalah ViewGroup yang sudah didekorasi dan hasilnya title yang ada di dalam Toolbar dapat diatur sesuka hati dengan menambahkan TextView didalamnya:

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:minHeight="?attr/actionBarSize"  
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:titleTextColor="@android:color/white"
    android:background="?attr/colorPrimary">

     <TextView
        android:id="@+id/toolbar_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Toolbar Title"
        android:textColor="@android:color/white"
        style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
        android:layout_gravity="center"
     />

</android.support.v7.widget.Toolbar>

Kita pun dapat mengakses TextView yang ada di dalam Toolbar di Activity:

/* Di dalam Activity */
// Mengatur Toolbar untuk sebagai ActionBar 
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Menghapus title default
getSupportActionBar().setDisplayShowTitleEnabled(false);
// Mengambil akses TextView yang ada di dalam Toolbar
TextView mTitle = (TextView) toolbar.findViewById(R.id.toolbar_title);

Hasilnya:

img

Status Bar Semi Transparan

Terkadang, status bar perlu terlihat semi transparan transparan seperti pada gambar di bawah:

img

Untuk mendapatkan hasil yang seperti ini, petama kita perlu mengatur properti berikut di dalam res/values/styles.xml theme utama (AppTheme):

<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>

Activity atau root layout yang ingin memiliki status bar yang transparan harus menambah properti fitsSystemWindows di XML:

<RelativeLayout
  android:fitsSystemWindows="true"
  ...
>

Baca jawaban stackoverflow post untuk pembahasan lebih detail.

Status Bar Transparan

Jika ingin status bar benar-benar transparan KitKat dan versi setelahnya, cara termudah ialah dengan:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  Window w = getWindow(); // di dalam onCreate
  w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}

lalu kemudian tambahkan style berikut di res/values/styles.xmltheme utama:

<item name="android:windowDrawsSystemBarBackgrounds">true</item>

Baca jawaban stackoverflow post untuk jawaban lebih detail.

Bereaksi terhadap Scroll

Kita dapat mengatur Toolbar agar bereaksi terhadap scroll:

img

Contoh di atas dapat dicapai dengan menggunakan CoordinatorLayout. Pertama, kita perlu menambahkan dependensi design support library ke file app/build.gradle:

dependencies {
    // ...
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.android.support:recyclerview-v7:23.1.0'
    compile 'com.android.support:design:23.1.0'
}

Lalu, di dalam layout XML activity misalnya res/layout/activity_main.xml, kita perlu mengatur agar CoordinatorLayout menjadi parent dariToolbar dan scrolling container contohnya RecyclerView:

<!-- CoordinatorLayout dipakai untuk membuat efek scrolling and "floating" di dalam sebuah layout -->
<!-- Pada umumnya ia akan menjadi root layout yang membungkus app bar dan konten -->
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main_content"
    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">

    <!-- AppBarLayout merupakan pembungkus bagi Toolbar di dalam CoordinatorLayout agar efek scrolling bekerja. -->
    <!-- Perlu dicatat bahwa AppBarLayout harus menjadi elemen pertama di dalam CoordinatorLayout -->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways" />
    </android.support.design.widget.AppBarLayout>

    <!-- Dapat juga dimasukkan dari layout lain dengan keyword include -->
    <!-- misalnya dimasukkan dari `res/layout/content_main.xml` jika menggunakan template Basic Activity -->
    <!-- `app:layout_behavior` untuk memberikan standard scrolling behavior yang telah disediakan -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

Tentu saja, RecyclerView dapat diganti dengan sebuah FrameLayout yang kemudian dapat ditimpa dengan sebuah fragment:

<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main_content"
    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">

    <!-- Masukkan AppBarLayout dan Toolbar seperti contoh sebelumnya! -->

    <!-- FrameLayout dapat dipakai untuk memasukkan fragment -->
    <!-- `app:layout_behavior` harus ditambahkan agar dapat melakukan scrolling dengan sebagaimana mestinya -->
    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
    />

</android.support.design.widget.CoordinatorLayout>

Contoh-contoh di atas menghasilkan aplikasi sebagai berikut:

img

Baca panduan CoordinatorLayout dan AppBarLayout untuk penjelasan lebih detail. Untuk troubleshooting baca troubleshooting guide.

Diterjemahkan dari Using the App ToolbarEdit PagePage History