2015年3月19日木曜日

AndroidのToolbarに触れてみよう。

この記事はイトナブ開発合宿にて作成されました。
イトナブ開発合宿を知らない方はまずこちらを御覧ください。
イトナブ開発合宿in滝沢市を開催しました。


【自己紹介】
はじめまして。「えんた」こと、遠藤拓也といいます。
岩手県立大学の2年で、普段は小・中・高生にプログラミングを教えたり、
AndroidアプリやWebサービスの開発を勉強していたりします。

イトナブ開発合宿はとても和やかな感じで開発ができて、分からない所や参考になりそうな
ところを教えてくださったり、ハッカソンとは違い徹夜して切羽詰まり…ということなく、
自分のペースで開発を進めていくことが出来ました。


【開発テーマ】
Android 5.0から使えるようになった、Toolbarとそのまわりをいじってみようと思います!


【Toolbarとは?】
Android 5.0 (Lollipop)と同時に追加されたActionBarの代替となるものです。
ビュー階層内に記述するため、他のビューとの共存や、アニメーション、スクロールイベントへの反応などが簡単にでき、
Activity の Action Bar として設定することもできるので、通常のオプション メニューのアクションをその内部に表示させることも可能です。


【開発環境
・Mac OS X (10.10.2)
・Android Studio(1.0.1)
・Android(5.0.1)


【試してみたこと】

・Toolbar
・Tab(Actionbar.Tabが非推奨になったため)
Navigation Drawer


 


【準備】
build.gradle(Module: app)
忘れないように、最初に追加しておきましょう。

dependencies {
     compile fileTree(dir: 'libs', include: ['*.jar'])
     // Toolbarを使うために必要
     compile 'com.android.support:appcompat-v7:21.0.0'
     // PagerSlidingTabStripを使うのに必要
     compile 'com.jpardogo.materialtabstrip:library:1.0.6'
}


================================================================================
styles.xml(v21)
Toolbarの色やステータスバーの色などはここで指定します。
parentはTheme.AppCompat…を使う必要があるみたいです。

<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
     < style name = "AppTheme" parent ="Theme.AppCompat.Light.NoActionBar" >
         <!-- Customize your theme here. -->
         <!-- Toolbarの背景色 -->
         < item name = "colorPrimary" >#FFBB33</ item >
         <!-- ステータスバーの背景色 -->
         < item name = "colorPrimaryDark" >#FFFF8800</ item >
         <!-- ActionModeを使うのに必要 -->
         < item name = "windowActionModeOverlay" >true</ item >
     </ style >
</ resources >



================================================================================
activity_main.xml
メインのレイアウト部分です。

<!-- Drawer start-->
< android.support.v4.widget.DrawerLayout xmlns:android = "http://schemas.android.com/apk/res/android"
     android:id = "@+id/drawer_layout"
     android:layout_width = "match_parent"
     android:layout_height = "match_parent" >
     < RelativeLayout 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:layout_width = "match_parent"
         android:layout_height = "match_parent"
         android:padding = "0dp"
         android:paddingBottom = "@dimen/activity_vertical_margin"
         android:paddingLeft = "@dimen/activity_horizontal_margin"
         android:paddingRight = "@dimen/activity_horizontal_margin"
         android:paddingTop = "@dimen/activity_vertical_margin"
         tools:context = ".MainActivity" >
         <!-- Tab -->
         < com.astuetz.PagerSlidingTabStrip
             android:id = "@+id/tabs"
             android:layout_width = "match_parent"
             android:layout_height = "48dp"
             android:layout_alignParentStart = "true"
             android:layout_below = "@+id/tool_bar"
             android:background = "?attr/colorPrimary" />
         < android.support.v4.view.ViewPager xmlns:android = "http://schemas.android.com/apk/res/android"
             android:id = "@+id/pager"
             android:layout_width = "match_parent"
             android:layout_height = "match_parent"
             android:layout_alignParentEnd = "false"
             android:layout_alignParentStart = "false"
             android:layout_below = "@+id/tool_bar"
             android:focusable = "false"
             android:nestedScrollingEnabled = "false"
             android:outlineProvider = "paddedBounds" >
             < android.support.v4.view.PagerTabStrip
                 android:id = "@+id/strip"
                 android:layout_width = "match_parent"
                 android:layout_height = "wrap_content"
                 android:background = "#FFBB33"
                 android:focusable = "false"
                 android:paddingBottom = "12dp"
                 android:paddingEnd = "15dp"
                 android:paddingStart = "15dp"
                 android:paddingTop = "12dp"
                 android:textColor = "#000"
                 android:touchscreenBlocksFocus = "true" />
         </ android.support.v4.view.ViewPager >
         <!-- ToolBar start -->
         < android.support.v7.widget.Toolbar
             android:id = "@+id/tool_bar"
             android:layout_width = "match_parent"
             android:layout_height = "wrap_content"
             android:layout_alignParentLeft = "true"
             android:layout_alignParentStart = "true"
             android:layout_alignParentTop = "true"
             android:background = "?attr/colorPrimary"
             android:minHeight = "?attr/actionBarSize"
             app:theme = "@style/ThemeOverlay.AppCompat.ActionBar" >
         </ android.support.v7.widget.Toolbar >
         <!-- ToolBar end -->
     </ RelativeLayout >
     <!-- Drawer 表示部分 -->
     < LinearLayout
         android:layout_width = "280dp"
         android:layout_height = "match_parent"
         android:layout_gravity = "start"
         android:background = "#fff" >
         < ListView
             android:id = "@+id/listview"
             android:layout_width = "fill_parent"
             android:layout_height = "match_parent" />
     </ LinearLayout >
     <!-- Drawer 表示部分 end -->
</ android.support.v4.widget.DrawerLayout >
<!-- Drawer end-->


?attrはstyles.xmlで付けた名前を使用しますよって意味


================================================================================
menu_main.xml
Toolbar右に表示されているメニューボタンです

< menu xmlns:android = "http://schemas.android.com/apk/res/android"
     xmlns:tools = "http://schemas.android.com/tools"
     xmlns:app = "http://schemas.android.com/apk/res-auto"
     tools:context = ".MainActivity" >
     < item android:id = "@+id/mbtn"
         android:title = "menu-button"
         android:icon = "@drawable/ic_launcher2” //顔マーク
         android:orderInCategory = "100"
         app:showAsAction = "ifRoom" />
</ menu >


================================================================================
activity_fragment(0〜2).xml
Tabで管理される画面です。今回は同様の画面を3つ用意しましした。

< 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" >
     < TextView
         android:layout_width = "match_parent"
         android:layout_height = "wrap_content"
         android:text = "グー"
         android:textSize = "30sp"
         android:padding = "50dp"
         android:layout_gravity = "center_vertical"
         android:gravity = "center" />
</ LinearLayout >


================================================================================
MainActivity.java
メイン部分です。

public class MainActivity extends ActionBarActivity {
     private DrawerLayout vDrawerLayout;
     private ActionBarDrawerToggle vDrawerToggle;
     private ListView vListView;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
         settoolbar();
         PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);
         ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
         mViewPager.setAdapter( newMyFragmentStatePagerAdapter(getSupportFragmentManager()));
         tabs.setViewPager(mViewPager);
         PagerTabStrip strip = (PagerTabStrip)findViewById(R.id.strip);
         strip.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20 );
         vDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
         initDrawer();
         vListView = (ListView) findViewById(R.id.listview);
         vListView.setAdapter( new ArrayAdapter<String>(
                 this , android.R.layout.simple_list_item_1, new String[]{ "menu 1" ,"menu 2" , "menu 3" , "menu 4" , "menu 5" }));
     }
     protected void settoolbar(){
         //  toolbar定義
         Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
         //  タイトル
         toolbar.setTitle( "ActionBar Title" );
         //  タイトルの色
         toolbar.setTitleTextColor(Color.parseColor( "#000000" ));
        //  ActionBarと同等にToolbarを使う  
      setSupportActionBar(toolbar);
     }
     private void initDrawer() {
         vDrawerToggle = new ActionBarDrawerToggle( this , vDrawerLayout, R.string.app_name, R.string.app_name);
         vDrawerToggle.setDrawerIndicatorEnabled( true );
         vDrawerLayout.setDrawerListener(vDrawerToggle);
         getSupportActionBar().setDisplayHomeAsUpEnabled( true );
         getSupportActionBar().setDisplayShowHomeEnabled( true );
     }
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.menu_main, menu);
         return true ;
     }
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
         if (id == R.id.mbtn) {
             Toast.makeText(MainActivity. this , "Menu click" , Toast.LENGTH_SHORT).show();
             return true ;
         }
         return vDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
     }
     @Override
     protected void onPostCreate(Bundle savedInstanceState) {
         super .onPostCreate(savedInstanceState);
         vDrawerToggle.syncState();
     }
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super .onConfigurationChanged(newConfig);
         vDrawerToggle.onConfigurationChanged(newConfig);
     }
}


================================================================================
MyFragmentStatePagerAdapter.java
FragmentStatePagerAdapterでFragmentを管理します。

public class MyFragmentStatePagerAdapter extends FragmentStatePagerAdapter {
     public MyFragmentStatePagerAdapter(FragmentManager fm) {
         super (fm);
     }
     @Override
     public Fragment getItem( int i) {
         switch (i){
             case 0 :
                 return new Fragment0();
             case 1 :
                 return new Fragment1();
             default :
                 return new Fragment2();
         }
     }
     @Override
     public int getCount() {
         return 3 ;
     }
     @Override
     public CharSequence getPageTitle( int position) {
         switch (position){
             case 0 :
                 return "First" ;
             case 1 :
                 return "Second" ;
             default :
                 return "Third" ;
         }
     }
}


================================================================================
Fragment(0〜2).java
Tabでスワイプして表示させる画面です。

public class Fragment0 extends Fragment {
     @Override
     public View onCreateView(LayoutInflater inflater,
                              ViewGroup container,
                              Bundle savedInstanceState) {
         return inflater.inflate(R.layout.activity_fragment0, null );
     }

    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         // Handle action bar item clicks here. The action bar will
         // automatically handle clicks on the Home/Up button, so long
         // as you specify a parent activity in AndroidManifest.xml.
         int id = item.getItemId();
         //noinspection SimplifiableIfStatement
         if (id == R.id.action_settings) {
             return true ;
         }
         return super .onOptionsItemSelected(item);
     }
}

長くなりましたが、これで
Toolbar、Tab、Navigation Drawerが実装出来たと思います。

【可能性】
ちょっと調べただけでもたくさんのサンプルが出てきました。
xmlでレイアウトを組むことが好きな私にとってはとても
使いやすいという印象がありました。
Actionbarの代わりとして扱え、さらにサイズや位置も自由に変えられるため、
Actionbar以外の使い道もアイディア次第になりそうです。
ただ、setSupportActionBarするとsetNavigationOnClickListenerやsetOnMenuItemClickListenerは
使えなくなるので注意。


【最後に】
普段は調べる→コピペ→動けばOK、という感じでしたが、
今回は『狭く、深く』ということだったので公式リファレンスを見たり、
実際にいろいろ試してみたり、英語とも格闘しました。すると、
点と点が繋がったようなことがあったり、今後の開発に活かせそうなことも
発見出来たりと、とても充実した時間を過ごすことができました。
今後も新しいことにどんどんチャレンジしていきたいと思います。


【Github】
コピペの量が多すぎ!って人はこちらをどうぞ


【参考】
Google Japan Developer Relations Blog

AndroidのToolBar(新しいActionBar)メモ


0 件のコメント:

コメントを投稿