※この記事はpotatotips45の発表をまとめたものです。
はじめに
ずっとiOSアプリの開発をしていましたが、ここ最近Androidのアプリの開発をはじめました。
iOSアプリとAndroidアプリでは仕組みや実装方法は違いますが、似たような機能や動きをするのでiOSで培った経験や考え方を活かしながら実装しています。
しかし最近、iOSアプリにはないUpボタン
の実装についてとても悩みました。
今回はそのUpボタン
について調べたことや実装方法についての紹介をしたいと思います。
AndroidのUpボタンとは?
UpボタンはAndroidのナビゲーションに関するものです。
iOSでいうところのNavigationBarのBackボタンやエッジスワイプにあたる機能になります。
AndroidのナビゲーションはUpボタンの他にBackボタンも存在します。
BackボタンはiOSのNavigationBarのBackボタン、エッジスワイプと同じで前の画面に戻るナビゲーションです。
Upボタンは、Backボタンとは違いただ前に戻るだけのナビゲーションではありません。
Upボタンは階層的な画面遷移
をするためのナビゲーションです。
階層的な画面遷移について
階層的な画面遷移とは、どこから来たかによって戻る画面が変わることです。
以下はGoogleのPlay Storeアプリの遷移例です。
1 ホームからの遷移
以下の用にアプリのホーム画面からアプリ詳細画面に遷移した際、Upボタンを押すとホーム画面に戻ります。
2 リストを挟んでの遷移
1とは違い、アプリのホーム画面からリスト画面(アプリの新着リストなど)を一旦挟みアプリ詳細に遷移するとリスト画面に戻ります。
実装について
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.xml
にPARENT_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.xml
にPARENT_ACTIVITY
を設定せず、Intent
を生成するようにしました。
また、普段は画面遷移をする際はstartActivity
を使用しますが、今回はnavigateUpTo
を使用します。
navigateUpTo
はIntent
で指定されたアクティビティに移動し、アクティビティを閉じるメソッドです。
動的に戻る画面遷移を実装する上で一番重要なのはIntent
のflags
にFLAG_ACTIVITY_CLEAR_TOP
を設定することです。
FLAG_ACTIVITY_CLEAR_TOP
を設定をすることで、画面が閉じられるような見た目になります。
これを設定しないで実行すると、新しく画面が作られたような見た目になってしまいます。
まとめ
- UpボタンはAndroidのナビゲーションに関するボタン
- 同じナビゲーションに関するボタンのBackボタンとは違い、階層的な画面遷移をする
- 戻る画面が変わる画面遷移をするには
Intent
を自前で生成する必要がある
以上がUpボタンについてのまとめです。
階層的な画面遷移を実装して、よりよいアプリにしていきたいですね!