The Toolbar Story
One of widgets that is worth mentioning — Toolbar. According to the documentation toolbar is a generalisation of action bars for use within application layouts. While an action bar is traditionally part of an Activity’s opaque window decor controlled by the framework, a Toolbar may be placed at any arbitrary level of nesting within a view hierarchy. An application may choose to designate a Toolbar as the action bar for an Activity using the setActionBar() method.
Since api 11 such design pattern is available to us as ActionBar which is a primary toolbar within the activity that may display the activity title, application-level navigation affordances, and other interactive items like menus.
Beginning with Android 3.0 (API level 11), the action bar appears at the top of an activity’s window when the activity uses the system’s Theme.Holo for Android 3.0 and above or AppCompat for Android 2.1 and above.
Flexibility and Key Functions of ActionBar
To be honest, the action bar was not flexible as far as customization is concerned: adding new or custom elements was hard and the logo or the application icon was almost mandatory. But it is a good design pattern which provided consistency for all applications on android device.
Here are the key functions that ActionBar provides:
- Helps express the app’s or brand’s unique identity
- Shows user’s location in the app
- Makes frequently used actions visible and accessible
- Supports design patterns such as tabs and drop-down lists for consistent navigation
The Toolbar
And with the arrival of the material design we have a new and more flexible widget — Toolbar, which can be used both as ActionBar and separately. It can take on any appearance, contain various widgets since the Toolbar class is extended from the ViewGroup, and not Object as is ActionBar. Also Toolbar is part of the layout, so it can be located in any part of the screen.
The widget is available not only in the api 21 but also in the AppCompat library. We will be using AppCompat so we need to use the class.
If we look at design spec of material design, specifically in the section dedicated to the structure of the window, we will see a huge number of possible applications of Toolbar.
We will display the details of the selected album. RecyclerView do not have a OnItemClickListener like ListView, so we will have to create a custom listener for clicking on the card from previously created list:
public class RecycleCardsAdapter extends RecyclerView.Adapter<RecycleCardsAdapter.CardViewHolder> implements View.OnClickListener { ...public interface RecycleOnItemClickListener { public void onOptionsClick(View view, int position); public void onItemClick(View view, int position); }@Override
public void onClick(View v) {
mListener.onItemClick(v, (Integer) v.getTag());
}… }
In the method onItemClick() in MainActivity we will be launching AlbumDetailsActivity using compatibility classes of AppCompat for Activity Transitions:
public class MainActivity extends ActionBarActivity implements RecycleCardsAdapter.RecycleOnItemClickListener { …@Override public void onItemClick(View view, int position) {
Intent intent = new Intent(MainActivity.this, AlbumDetailsActivity.class); intent.putExtra(Const.ALBUM_INTENT_EXTRA, mAlbums.get(position)); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(MainActivity.this, view, getString(R.string.text_art)); ActivityCompat.startActivity(MainActivity.this, intent, options.toBundle()); } … }
Also create AlbumDetailsActivity class to display the cover, artist and song list of the selected album. Let’s add toolbar to this activity, which will act as a transparent action bar.
Here is the layout of AlbumDetailsActivity:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".AlbumDetailsActivity"><LinearLayout android:id="@+id/lyt_about" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:transitionName="@string/text_art" android:background="#ffc7c7c7"> <com.the111mins.newwidgetsprojects.ui.widget.SquareImageView android:id="@+id/image_art" android:layout_width="match_parent" android:layout_height="wrap_content" tools:src="@drawable/savages"/> <TextView android:id="@+id/txt_album_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="@dimen/fifteen_dp" android:paddingTop="@dimen/fifteen_dp" android:textSize="@dimen/text_size_medium" android:textStyle="bold" tools:text="Savages"/> <TextView android:id="@+id/txt_album_artist" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="@dimen/fifteen_dp" android:paddingBottom="@dimen/fifteen_dp" tools:text="Breathe Carolina"/></LinearLayout><android.support.v7.widget.RecyclerView android:id="@+id/recycle_view_songs" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/lyt_about" android:scrollbars="vertical"/> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/image_shadow" android:minHeight="50dp" custom:navigationContentDescription="@string/text_go_back" custom:navigationIcon="@drawable/ic_action_arrow_back" custom:popupTheme="@style/ThemeOverlay.AppCompat.Dark" custom:theme="@style/TransparentActionBar"/> </RelativeLayout>
The style used for the toolbar:
<style name="TransparentActionBar" parent="ThemeOverlay.AppCompat.Dark.ActionBar"> <item name="android:displayOptions">showHome|useLogo</item><item name="android:titleTextStyle">@style/TransparentActionBar.TitleTextStyle</item>
</style>
<style name="TransparentActionBar.TitleTextStyle" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
<item name="android:textSize">24sp</item> <item name="android:textColor">@android:color/white</item></style>
Style used for activity, as we need to turn off the action bar, which is provided by default if the activity extends ActionBarActivity:
<style name="DetailsTheme" parent="AppTheme"> <item name="windowActionBar">false</item> </style>
In AlbumDetailsActivity find the toolbar and set it as the action bar:
public class AlbumDetailsActivity extends ActionBarActivity { private Album mAlbum; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_album_details);setupToolbar();mAlbum = (Album) getIntent().getSerializableExtra(Const.ALBUM_INTENT_EXTRA);createUI();configureRecyclerView();}private void setupToolbar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); toolbar.setNavigationOnClickListener(new View.OnClickListener() {@Override
public void onClick(View v) {
onBackPressed();
}
});}
private void configureRecyclerView() { RecyclerView songsRecycleView = (RecyclerView) findViewById(R.id.recycle_view_songs); songsRecycleView.setHasFixedSize(true); LinearLayoutManager recycleLayoutManager = new LinearLayoutManager(this);
songsRecycleView.setLayoutManager(recycleLayoutManager); songsRecycleView.setItemAnimator(new DefaultItemAnimator()); RecycleSongsAdapter songsAdapter = new RecycleSongsAdapter(mAlbum.getSongTitles()); songsRecycleView.setAdapter(songsAdapter);
}…}
The menu will now be displayed in the toolbar!
To display a list of songs we will use RecyclerView with LinearLayoutManager to show items as a list.
public class RecycleSongsAdapter extends RecyclerView.Adapter<RecycleSongsAdapter.SongViewHolder> { private final String[] mSongs; public RecycleSongsAdapter(String[] songsArray) {
this.mSongs = songsArray; }public static class SongViewHolder extends RecyclerView.ViewHolder {private TextView songTitle;public SongViewHolder(View itemView) { super(itemView);
this.songTitle = (TextView) itemView.findViewById(android.R.id.text1);} }@Override
public RecycleSongsAdapter.SongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()) .inflate(android.R.layout.simple_list_item_1, parent, false);return new SongViewHolder(view);}@Override
public void onBindViewHolder(RecycleSongsAdapter.SongViewHolder holder, final int listPosition) { holder.songTitle.setText(mSongs[listPosition]); } @Override
public int getItemCount() {
return mSongs.length; } }
How it looks:
Written by: Yana Klimenko on April 16, 2015.
Originally published at 111 Minutes Blog.