Android StudioのActivityTemplate全部試してみた!(2/2)

前回に引き続き、AndroidStudioのActivityのサンプルを試してみます。 残り6個!

目次

  • LoginActivity
  • Master/Detail Flow
  • TabbedActivity
  • SettingsActivity
  • ScrollingActivity
  • NavigationDrawer

LoginActivity

f:id:t-miliya612:20180510205338p:plain

特徴

  • 一般的なログインフォーム
  • 補完機能などUIが充実

Source

xml

<!-- プログレスバー -->
<ProgressBar
    android:id="@+id/login_progress"
    style="?android:attr/progressBarStyleLarge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:visibility="gone" />
<!-- メールアドレスの補完機能がついたTextView -->
<AutoCompleteTextView
    android:id="@+id/email"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/prompt_email"
    android:inputType="textEmailAddress"
    android:maxLines="1"
    android:singleLine="true" />

自動補完用のTextViewなんてあったんですね。

Activity

長いのでメソッド名だけ、

  • permission処理
    • mayRequestContacts()
    • onRequestPermissionResult(Int, Array, IntArray)
  • 連絡帳アクセス
    • onCreateLoader(Int, Bundle?)
    • onLoadFinished(Loader>Cursor>, Cursor)
  • textViewに補完
    • addEmailsToAutoComplete(List)
  • 通信処理
    • inner class UserLoginTask
  • プログレスダイアログ
    • showProgress(Boolean)

機能だけでなく、UX的な面でも参考になります……!

Master/Detail Flow

f:id:t-miliya612:20180510212411p:plain

特徴

  • リストをタップすると詳細画面が表示される
  • スマホだと画面遷移、タブレットだとペイン表示

Source

基本は一般的なActivityとFragmentです。特徴的なのは、出し分けのロジックですね。
今回はこれを2つのitem_list.xmlの呼び分けで実現しています。app/src/main/res/layoutにあるものが呼ばれていればスマホサイズ、app/src/main/res/layout-w900dpのものが呼ばれていればタブレットサイズとなります。

Activity

if (item_detail_container != null) {
    // The detail container view will be present only in the
    // large-screen layouts (res/values-w900dp).
    // If this view is present, then the
    // activity should be in two-pane mode.
    twoPane = true
}
onClickListener = View.OnClickListener { v ->
    val item = v.tag as DummyContent.DummyItem
    // タブレットかどうか
    if (twoPane) {
        val fragment = ItemDetailFragment().apply {
            arguments = Bundle().apply {
                putString(ItemDetailFragment.ARG_ITEM_ID, item.id)
            }
        }
        parentActivity.supportFragmentManager
                .beginTransaction()
                .replace(R.id.item_detail_container, fragment)
                .commit()
    } else {
        val intent = Intent(v.context, ItemDetailActivity::class.java).apply {
            putExtra(ItemDetailFragment.ARG_ITEM_ID, item.id)
        }
        v.context.startActivity(intent)
    }
}

TabbedActivity

特徴

3種類のスタイルがあります。

  • Swipe Views

f:id:t-miliya612:20180510204831p:plain

  • Action Bar Tabs

f:id:t-miliya612:20180510204917p:plain

  • Action Bar Spinner

f:id:t-miliya612:20180510204928p:plain

が、、、全体的に上手くいきませんでした。
SwipeViewsはデザインが違い、その他はそもそもビルドが出来ませんでした。
AndroidStudioのバージョンにもよるのでしょうが、別途自分で書いてみます。

SettingsActivity

f:id:t-miliya612:20180510205219p:plainf:id:t-miliya612:20180510205225p:plain

特徴

アプリの設定画面を生成してくれます。
アプリ内で完結したいものは、OSの設定画面へと遷移してくれます。

Source

AppCompatPreferenceAcrivityでPreferenceごとにFragmentを定義しています。

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
class GeneralPreferenceFragment : PreferenceFragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        addPreferencesFromResource(R.xml.pref_general)
        setHasOptionsMenu(true)

        // Bind the summaries of EditText/List/Dialog/Ringtone preferences
        // to their values. When their values change, their summaries are
        // updated to reflect the new value, per the Android Design
        // guidelines.
        bindPreferenceSummaryToValue(findPreference("example_text"))
        bindPreferenceSummaryToValue(findPreference("example_list"))
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        val id = item.itemId
        if (id == android.R.id.home) {
            startActivity(Intent(activity, SettingsActivity::class.java))
            return true
        }
        return super.onOptionsItemSelected(item)
    }
}

の繰り返しです。

また、xml/pref_xxxでpreferenceごとの画面を定義しています。

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
         dismiss it. -->
    <!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
    <ListPreference
        android:defaultValue="180"
        android:entries="@array/pref_sync_frequency_titles"
        android:entryValues="@array/pref_sync_frequency_values"
        android:key="sync_frequency"
        android:negativeButtonText="@null"
        android:positiveButtonText="@null"
        android:title="@string/pref_title_sync_frequency" />

    <!-- This preference simply launches an intent when selected. Use this UI sparingly, per
         design guidelines. -->
    <Preference android:title="@string/pref_title_system_sync_settings">
        <intent android:action="android.settings.SYNC_SETTINGS" />
    </Preference>

</PreferenceScreen>

こうやって使うんですね。

ScrollingActivity

f:id:t-miliya612:20180510205238p:plain

特徴

  • CollapsingToolbarLayoutの中に配置したAppBarの大きさが可変になる

Source

そのままじゃ上手く表示されなかったのでちょっと修正……

以前紹介した本を参考にしました。

t-miliya612.hatenablog.com

xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:elevation="10dp">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbarLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

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

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".ScrollingActivity"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_mar[f:id:t-miliya612:20180510205238p:plain]gin="@dimen/text_margin"
            android:text="@string/large_text" />

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

app:layout_behavior="@string/appbar_scrolling_view_behavior"を忘れるとコンテントの文字が被ってしまうので要注意です。

NavigationDrawer

f:id:t-miliya612:20180510205432p:plain

特徴

  • 左側から出てくるタイプのナビゲーション

Source

設定は結構簡単でした。

Activity

val toggle = ActionBarDrawerToggle(
        this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawer_layout.addDrawerListener(toggle)
toggle.syncState()

nav_view.setNavigationItemSelectedListener(this)

activity_navigation_drawer.xml

...

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_navigation_drawer"
        app:menu="@menu/activity_navigation_drawer_drawer" />

...

layout/nav_header_navigation_drawer.xml

<?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="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/nav_header_desc"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        app:srcCompat="@mipmap/ic_launcher_round" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="@string/nav_header_title"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/nav_header_subtitle" />

</LinearLayout>

menu/activity_navigation_drawer_drawer.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_camera"
            android:icon="@drawable/ic_menu_camera"
            android:title="Import" />
        <item
            android:id="@+id/nav_gallery"
            android:icon="@drawable/ic_menu_gallery"
            android:title="Gallery" />
        <item
            android:id="@+id/nav_slideshow"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="Slideshow" />
        <item
            android:id="@+id/nav_manage"
            android:icon="@drawable/ic_menu_manage"
            android:title="Tools" />
    </group>

    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_menu_share"
                android:title="Share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@drawable/ic_menu_send"
                android:title="Send" />
        </menu>
    </item>

</menu>

まとめ

全体的に学習材料として面白かったです。ただ、Tab系のActivityは謎でした……結構使いそうな気がするんだけどなぁ。
初めて実装する際には、手直しのことも考えるとEmptyActivityで頑張った方がよさそうですね。

そして、 初めから全部で2記事って決めると大変つらいことになる という学びを得ました。以上です。