Tutorial Android Material Design
Tahu kan sekarang lagi musimnya material design? Mau tidak mau juga harus mengikutinya biar menjadi kekinian. Disini kita akan membuat aplikasi android dengan menggunakan android design support library, seperti : NavigationView
, TabLayout
, TextInputLayout
, Snackbar
, CoordinatorLayout
, AppBarLayout
, CollapsingToolbarLayout
dan FloatingActionButton
yang akan bermaterialan.
build.gradle #
Yang pertama adalah menambahkan library ke dalam project kita. Jika baru pertama kali / sewaktu update ke versi lainnya, pastikan terhubung dengan koneksi internet. Edit build.gradle
seperti berikut ini:
public class Constant {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:design:22.2.1' //tambahkan ini dan gunakanlah versi terbaru
compile 'com.jakewharton:butterknife:7.0.1' //opsional
compile 'de.hdodenhof:circleimageview:1.3.0' //opsional
}
}
Setelah berhasil menambahkan library kedalam project kita. Selanjutnya kita mulai koding rianya.
strings.xml #
<resources>
<string name="app_name">Njajal Material</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="open">Open</string>
<string name="close">Close</string>
</resources>
String open dan close akan digunakan di ActionBarDrawerToggle()
color.xml #
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#ff2f88b5</color>
<color name="primary_dark">#ff29769f</color>
<color name="accent">#ffff61cd</color>
</resources>
styles.xml (values) #
Jika anda membuat aplikasi dengan versi minimum SDK kurang dari 21 alangkah lebih baiknya buat 2 buah styles.xml
, yang satu pada folder values (default), dan yang satunya pada folder values-v21.
<resources>
<!-- Base application theme. -->
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22AppTheme%22%20parent%3D%22Theme.AppCompat.Light.DarkActionBar%22%3E%0A%20%20%20%20%20%20%20%20%3C!--%20Customize%20your%20theme%20here.--%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22windowNoTitle%22%3Etrue%3C%2Fitem%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22windowActionBar%22%3Efalse%3C%2Fitem%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22colorPrimary%22%3E%40color%2Fprimary%3C%2Fitem%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22colorPrimaryDark%22%3E%40color%2Fprimary_dark%3C%2Fitem%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22colorAccent%22%3E%40color%2Faccent%3C%2Fitem%3E%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;style&gt;" title="&lt;style&gt;" />
</resources>
styles.xml (values-v21) #
Pada styles.xml
di folder values-v21 tambahkan baris dibawah ini untuk membuat DrawerLayout
dan NavigationView
fullscreen ketika dibuka, sehingga warna statusBar
mengikuti header dari NavigationView
.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%20name%3D%22AppTheme%22%20parent%3D%22Theme.AppCompat.Light.DarkActionBar%22%3E%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22android%3AwindowDrawsSystemBarBackgrounds%22%3Etrue%3C%2Fitem%3E%0A%20%20%20%20%20%20%20%20%3Citem%20name%3D%22android%3AstatusBarColor%22%3E%40android%3Acolor%2Ftransparent%3C%2Fitem%3E%0A%20%20%20%20%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;style&gt;" title="&lt;style&gt;" />
</resources>
menu_drawer.xml #
menu_drawer.xml
saya gunakan untuk menu didalam NavigationView
.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:id="@+id/nav_home" android:icon="@drawable/ic_home_black_24dp" android:title="Home" />
<item android:id="@+id/nav_messages" android:icon="@drawable/ic_message_black_24dp" android:title="Messages" />
<item android:id="@+id/nav_friends" android:icon="@drawable/ic_people_black_24dp" android:title="Friends" />
<item android:id="@+id/nav_communities" android:icon="@drawable/ic_group_work_black_24dp" android:title="Communities" />
</group>
</menu>
header.xml #
menu_drawer.xml
saya gunakan untuk menu didalam NavigationView
.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:id="@+id/nav_home" android:icon="@drawable/ic_home_black_24dp" android:title="Home" />
<item android:id="@+id/nav_messages" android:icon="@drawable/ic_message_black_24dp" android:title="Messages" />
<item android:id="@+id/nav_friends" android:icon="@drawable/ic_people_black_24dp" android:title="Friends" />
<item android:id="@+id/nav_communities" android:icon="@drawable/ic_group_work_black_24dp" android:title="Communities" />
</group>
</menu>
header.xml #
Header disini merupakan layout yang saya gunakan sebagai header pada NavigationView
.
<?xml version="1.0" encoding="utf-8"?>
<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="200dp" android:background="@drawable/bg" android:gravity="bottom" android:orientation="vertical" android:padding="20dp">
<de.hdodenhof.circleimageview.CircleImageView android:id="@+id/imgUser" android:layout_width="100dp" android:layout_height="100dp" app:border_color="@android:color/white" app:border_width="2dp" android:src="@drawable/pev" />
<TextView android:layout_marginTop="5dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Pevita Pearce" android:textColor="@android:color/white" android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
activity_main.xml #
Berikut struktur layout activity_main.xml
:
<android.support.v4.widget.DrawerLayout ... >
<android.support.design.widget.CoordinatorLayout ... >
<android.support.design.widget.AppBarLayout ... >
<android.support.design.widget.CollapsingToolbarLayout ... >
<ImageView ... />
<android.support.v7.widget.Toolbar ... />
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout ... />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager ... />
<android.support.design.widget.FloatingActionButton .../>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView ... />
</android.support.v4.widget.DrawerLayout>
Pada CollapsingToolbarLayout
untuk defaultnya saya memakai scroll|exitUntilCollapsed
agar ImageView
yang ada di dalamnya collapsed ketika scroll kebawah dan expanded ketika scroll keatas ketika scroll sudah pada posisi 0 (scroll sampai atas habis). Selain exitUntilCollapsed
ada juga enterAlways
yang berfungsi ketika scroll kebawah dan keatas akan collapsed dan expanded selalu. Dan ada juga enterAlwaysCollapsed
. Alangkah lebih baiknya mencoba semuanya, agar dapat cepat memahami.
...
<android.support.design.widget.CollapsingToolbarLayout ... app:layout_scrollFlags="scroll|exitUntilCollapsed">
...
</android.support.design.widget.CollapsingToolbarLayout>
...
Untuk memberikan paralax effect pada ImageView
yang ada didalam CollapsingToolbarLayout
cukup menambahkan:
...
<ImageView ... app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7"/>
...
Agar Toolbar tidak ikut hilang ketika scroll keatas kita beri kode:
...
<android.support.v7.widget.Toolbar ... app:layout_collapseMode="pin"/>
...
Sedangkan TabLayout
tempatkan di dalam AppBarLayout
bukan didalam CollapsingToolbarLayout
dan bukan diluar AppbarLayout
yang bertujuan agar ketika kita scroll kebawah akan berhenti dibawah Toolbar dan ketika scroll keatas sampai habis, akan mengexpand dan posisi TabLayout
akan dibawah ImagView
.
<android.support.design.widget.AppBarLayout ... >
<android.support.design.widget.CollapsingToolbarLayout ... >
...
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout ... />
</android.support.design.widget.AppBarLayout>
ViewPager
dan FloatingActionButton
tempatkan diluar CollapsingToolbarLayout serta jangan lupa menambahkan:
<android.support.design.widget.CoordinatorLayout ... >
...
<android.support.v4.view.ViewPager ... app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton ... />
</android.support.design.widget.CoordinatorLayout>
Pada ViewPager yang berfungsi sebagai patokan scroll. Ketika di scroll, posisi ViewPager
tetap dibawah AppBarLayout
. Dan kalau ada widget atau layout yang tertimpa / sembunyi / ketutup, kita bisa memainkan atau menambahkan:
<android.support.v4.widget.DrawerLayout ... android:fitsSystemWindows="true">
...
</android.support.v4.widget.DrawerLayout>
Berikut kode lengkap dari activity_main.xml
:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context=".MainActivity">
<android.support.design.widget.CoordinatorLayout android:id="@+id/coordinatorLayout" android:layout_height="match_parent" android:layout_width="match_parent">
<android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsingToolbar" android:layout_width="match_parent" android:layout_height="192dp" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:expandedTitleMarginStart="64dp" app:contentScrim="?attr/colorPrimary">
<ImageView android:id="@+id/img" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/ra" android:scaleType="centerCrop" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7"/>
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" android:theme="@style/ThemeOverlay.AppCompat.Dark" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:background="?attr/colorPrimary" app:tabMode="fixed" app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_mode_edit_white_24dp" android:layout_gravity="bottom|end" app:fabSize="normal" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:layout_margin="15dp"/>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView android:id="@+id/navView" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:clickable="true" app:headerLayout="@layout/header" app:menu="@menu/menu_drawer" />
</android.support.v4.widget.DrawerLayout>
fragment_ngopi.xml #
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" >
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="lakdclkadca jhbjh kjnkj akdnclakdcla jhkh jjkn ladclakmdclakmdclakmdclakmdclakdmcal lakdmclakmdclkamdclkamdclkmaldkc lakdmclakdclkadlckalkdc kdlckmlkmalkdmclkmlkmlkmadkmlkmclkm kmadlc kdc lkdc alkd clkd clka dclkac lakdc la calkd calkdc alkd calkd clak dcalkcda lakdmclakdmclkad caldclakdcmald calkd calkd calkd clad clakc akdmclakdmcad cla" android:textSize="50dp"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
fragment_turu.xml #
Di layout fragment_turu.xml
ini saya sertakan juga TextInputLayout
yang juga dari android design support library, dengan menggunakan TextInputLayout
sekarang tidak ribet lagi untuk membuat pesan error didalam EditText
ataupun membuat TextView
untuk keterangan di EditText
(cukup menggunakan hint). Cara penggunaannya seperti berikut ini:
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPersonName" android:hint="Title"/>
</android.support.design.widget.TextInputLayout>
Berikut kode lengkap layout fragment_turu.xml
:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" >
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPersonName" android:hint="Title"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPersonName" android:hint="Date"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content">
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textPersonName" android:hint="Descripion"/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
NgopiFragment.java #
public class NgopiFragment extends Fragment {
public NgopiFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_ngopi, container, false);
}
}
TuruFragment.java #
public class TuruFragment extends Fragment {
public TuruFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_turu, container, false);
}
}
ViewPagerAdapter.java #
public class ViewPagerAdapter extends FragmentPagerAdapter {
private String[] TAB_TITLE = {"Ngopi", "Turu"};
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new NgopiFragment();
case 1:
return new TuruFragment();
}
return null;
}
@Override
public int getCount() {
return TAB_TITLE.length;
}
@Override
public CharSequence getPageTitle(int position) {
return TAB_TITLE[position];
}
}
MainActivity.java #
Menampilkan Snackbar: #
Snackbar.make(v,"Tenan pora?", Snackbar.LENGTH_LONG)
.setAction("Iyo leh", this)
.show();
Setup Toolbar: #
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);
Setup ActionBarDrawerToggle: #
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.open,
R.string.close
);
drawerLayout.setDrawerListener(toggle);
toggle.syncState();
Setup NavigationView: #
//yang di cek pertama
navView.getMenu().getItem(0).setChecked(true);
navView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
drawerLayout.closeDrawers();
int id = menuItem.getItemId();
switch (id) {
case R.id.nav_home:
showToast("Nav Home");
break;
case R.id.nav_messages:
showToast("Nav Messages");
break;
case R.id.nav_friends:
showToast("Nav Friends");
break;
case R.id.nav_communities:
showToast("Nav Communities");
break;
}
return false;
}
}
);
Setup CollapsingToolbarLayout title: #
collapsingToolbar.setTitle(toolbar.getTitle());
Setup TabLayout: #
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
Berikut kode lengkap dari MainActivity.java
:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Bind(R.id.toolbar)
Toolbar toolbar;
@Bind(R.id.drawerLayout)
DrawerLayout drawerLayout;
@Bind(R.id.collapsingToolbar)
CollapsingToolbarLayout collapsingToolbar;
@Bind(R.id.navView)
NavigationView navView;
@Bind(R.id.tabLayout)
TabLayout tabLayout;
@Bind(R.id.viewPager)
ViewPager viewPager;
@OnClick(R.id.fab) void fabOnClick(View v) {
Snackbar.make(v,"Tenan pora?", Snackbar.LENGTH_LONG)
.setAction("Iyo leh", this)
.show();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setupToolbarToggle();
setupNavView();
setupCollapseToolbar();
setupTabLayout();
}
private void setupToolbarToggle() {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this,
drawerLayout,
toolbar,
R.string.open,
R.string.close
);
drawerLayout.setDrawerListener(toggle);
toggle.syncState();
}
private void setupNavView() {
//yang di cek pertama
navView.getMenu().getItem(0).setChecked(true);
navView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
drawerLayout.closeDrawers();
int id = menuItem.getItemId();
switch (id) {
case R.id.nav_home:
showToast("Nav Home");
break;
case R.id.nav_messages:
showToast("Nav Messages");
break;
case R.id.nav_friends:
showToast("Nav Friends");
break;
case R.id.nav_communities:
showToast("Nav Communities");
break;
}
return false;
}
}
);
}
private void setupCollapseToolbar() {
collapsingToolbar.setTitle(toolbar.getTitle());
}
private void setupTabLayout() {
viewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
}
private void showToast(String toast) {
Toast.makeText(this, toast, Toast.LENGTH_SHORT).show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
drawerLayout.openDrawer(GravityCompat.START);
return true;
case R.id.action_settings:
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {}
}
Setelah selesai semuanya, sekarang tinggal jalankan aplikasinya. Untuk hasilnya bisa lihat video diatas.
Ternyata dengan Android design support library kita tidak dibuat njelimet lagi untuk membuat ini itu, hanya dengan bermain layout, aplikasi yang kita buat bisa jadi lebih menarik dan kekinian.
Semoga bermanfaat.