Edited at
VASILYDay 7

iOSエンジニアが悩んだAndroidのUpボタンについて

More than 1 year has passed since last update.

※この記事はpotatotips45の発表をまとめたものです。


はじめに

ずっとiOSアプリの開発をしていましたが、ここ最近Androidのアプリの開発をはじめました。

iOSアプリとAndroidアプリでは仕組みや実装方法は違いますが、似たような機能や動きをするのでiOSで培った経験や考え方を活かしながら実装しています。

しかし最近、iOSアプリにはないUpボタンの実装についてとても悩みました。

今回はそのUpボタンについて調べたことや実装方法についての紹介をしたいと思います。


AndroidのUpボタンとは?

UpボタンはToolbarの左側にあるボタンです。

スクリーンショット 2017-12-03 0.44.42.png

UpボタンはAndroidのナビゲーションに関するものです。

iOSでいうところのNavigationBarのBackボタンやエッジスワイプにあたる機能になります。

AndroidのナビゲーションはUpボタンの他にBackボタンも存在します。

スクリーンショット 2017-12-03 0.52.49.png

BackボタンはiOSのNavigationBarのBackボタン、エッジスワイプと同じで前の画面に戻るナビゲーションです。

Upボタンは、Backボタンとは違いただ前に戻るだけのナビゲーションではありません。

Upボタンは階層的な画面遷移をするためのナビゲーションです。


階層的な画面遷移について

階層的な画面遷移とは、どこから来たかによって戻る画面が変わることです。

以下はGoogleのPlay Storeアプリの遷移例です。

1 ホームからの遷移

以下の用にアプリのホーム画面からアプリ詳細画面に遷移した際、Upボタンを押すとホーム画面に戻ります。

スクリーンショット 2017-12-03 1.36.16.png

2 リストを挟んでの遷移

1とは違い、アプリのホーム画面からリスト画面(アプリの新着リストなど)を一旦挟みアプリ詳細に遷移するとリスト画面に戻ります。

スクリーンショット 2017-12-03 1.37.50.png


実装について

Upボタンの実装については、Android Developerに実装についての参考があります。

以下がサンプルコードです。

<application ... >

...
<activity
android:name="com.example.myfirstapp.MainActivity" ...>
...
</activity>
<activity
android:name="com.example.myfirstapp.DisplayMessageActivity"
android:label="@string/title_activity_display_message"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
</activity>
</application>


override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
val upIntent = NavUtils.getParentActivityIntent(this)
if (NavUtils.shouldUpRecreateTask(this, upIntent!!)) {
// 戻る先のタスクがないので生成する
TaskStackBuilder.create(this)
.addNextIntentWithParentStack(upIntent)
.startActivities()
} else {
NavUtils.navigateUpTo(this, upIntent)
}
return true
}
}
return super.onOptionsItemSelected(item)
}

AndroidManifest.xmlPARENT_ACTIVITYを設定しています。

Upボタンを押して画面を戻るときに、NavUtils.getParentActivityIntent(this)で指定したPARENT_ACTIVITYを取得して画面遷移をしています。

実装としてはすごくシンプルだと思います。

しかし、この実装方法ではPARENT_ACTIVITYが固定されてしまうので戻る画面が静的になってしまいます。


戻る画面が動的に変わる実装方法

Play Storeのような動的に戻る画面遷移を実現するために、以下のように実装しました。

実装方法


  • 戻りたい画面のIntentを生成する

  • navigateUpToを使用する


  • IntentにFLAG_ACTIVITY_CLEAR_TOPを設定する

コード

class ChildActivity : AppCompatActivity(), ItemDetailEventHandler {

private lateinit var fromActivity: FromActivity
private const val FROM_ACTIVITY = "from_activity"

enum class FromActivity {
HOME,
SEARCH_RESULT,
・・・
}

companion object {
private const val FROM_ACTIVITY = "from_activity"

fun start(context: Context, fromActivity: FromActivity) {
context.startActivity(
Intent(context, ChildActivity::class.java).apply {
putExtra(FROM_ACTIVITY, fromActivity)
})
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

fromActivity = intent.getSerializableExtra(FROM_ACTIVITY) as FromActivity
}

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
android.R.id.home -> {
val intent = createIntent(fromActivity)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
navigateUpTo(intent)

return true
}
else -> return false
}
}

private fun createIntent(fromActivity: FromActivity): Intent {
return when (fromActivity) {
FromActivity.HOME -> Intent(this, HomeActivity::class.java)
FromActivity.SEARCH_RESULT -> Intent(this, SearchItemResultActivity::class.java)
・・・
}
}
}

class HomeActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

ChildActivity.start(context, ItemDetailActivity.FromActivity.ITEM_RANKING)
}
}

戻る画面が動的になるため、AndroidManifest.xmlPARENT_ACTIVITYを設定せず、Intentを生成するようにしました。

また、普段は画面遷移をする際はstartActivityを使用しますが、今回はnavigateUpToを使用します。

navigateUpToIntentで指定されたアクティビティに移動し、アクティビティを閉じるメソッドです。

動的に戻る画面遷移を実装する上で一番重要なのはIntentflagsFLAG_ACTIVITY_CLEAR_TOPを設定することです。

FLAG_ACTIVITY_CLEAR_TOPを設定をすることで、画面が閉じられるような見た目になります。

これを設定しないで実行すると、新しく画面が作られたような見た目になってしまいます。


まとめ


  • UpボタンはAndroidのナビゲーションに関するボタン

  • 同じナビゲーションに関するボタンのBackボタンとは違い、階層的な画面遷移をする

  • 戻る画面が変わる画面遷移をするにはIntentを自前で生成する必要がある

以上がUpボタンについてのまとめです。

階層的な画面遷移を実装して、よりよいアプリにしていきたいですね!


参考資料

Back ボタンと Up ボタンを使用したナビゲーション