デザインの大幅変更 〜Bottom Navigation〜

公開 2019-05-24 / 最終更新 2021-05-05 12:07
カテゴリー Androidアプリ

今回は、アプリのデザインの大幅な変更にチャレンジしていこうと思います。今までは上部に表示するためのTabをそのまま下に配置していたので、そこを直していきます。また、左から引っ張り出してくるドロワーも廃止します。ドロワーを採用しているアプリは最近だんだん減ってきているように思えますね。

これらのデザインを提唱している団体は、「Material Design」といって、要するに**Googleです。**Playストアに存在する大体のアプリがこれに則って作られています。個人開発のアプリはだいたいこれです。

方法

まず、既存のMainActivityを潰すとうまく行かなかったとき面倒なことになるので、新しくMain2Activityを作ります。テンプレートが既に用意されているというのもあります。Appを右クリックし、New→Activity→Bottom Navigation Activityの順にクリックすれば作れます。

以前までは下部のナビゲーションはiOSだけのもので禁忌だったらしいのですが、最近Material Designが急に提唱しだしたらしいです。(最近始めたばかりのプログラマーなので「らしい」連発)

画面切り替えの方法ですが、いろいろ調べた結果ViewPagerで切り替えるのが一番いいらしい。ただし、何もいじらず使うのはMaterial Designが言うにはアウトらしいので、弄ってから使います。

まず、ViewPagerをスワイプで切り替えできなくします。スワイプ出来てしまうとタッチイベントをViewPagerに奪われてスワイプしづらくなるなど、その他のアプリの機能に支障をきたします。画面切り替えは基本下部のボタンだけです。

スワイプ出来ないViewPagerを自作します。

NonSwipeViewPager.kt

package net.chikach.smmanager

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class NonSwipeViewPager(context: Context, attributeSet: AttributeSet) : ViewPager(context, attributeSet) {

    override fun onTouchEvent(ev: MotionEvent?): Boolean = false
    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean = false

}

タッチイベントを無効化しているだけで特に難しいことはしてないです。

次に、ナビゲーションバーの中身を設定します。optionsMenuのようにmenuフォルダーにxmlを作成します。

bottom_nav_menu.xml

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

    <item
        android:id="@+id/navigation_home"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/title_submission" />

    <item
        android:id="@+id/navigation_dotime"
        android:icon="@drawable/completed_submissions"
        android:title="@string/title_dotime" />

    <item
        android:id="@+id/navigation_timetable"
        android:icon="@drawable/baseline_table_chart_black_48"
        android:title="@string/title_timetable" />

    <item
        android:id="@+id/navigation_memorize"
        android:icon="@drawable/memorize_card"
        android:title="@string/drawer_memCard" />

    <item
        android:id="@+id/navigation_others"
        android:icon="@drawable/baseline_more_horiz_white_48"
        android:title="@string/title_others" />

</menu>

strings.xml(一部分)

<string name="title_submission">提出物</string>
<string name="title_dotime">DoTime</string>
<string name="title_timetable">時間割</string>
<string name="drawer_memCard">暗記カード</string>
<string name="title_others">その他</string>

次に、ViewPagerのアダプターと画面ごとのフラグメントを作ります。前までActivityとして書いていたものをFragmentとして移植するだけです。コードはGitHubに載せておくので見たい方は見てください。

次に、ボトムナビを押したときに起きる処理を書きます。イベントハンドラーは「OnNavigationItemSelectedListener」です。

Main2Activity.kt

    private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        return@OnNavigationItemSelectedListener when (item.itemId) {
            R.id.navigation_home -> {
                changePage(0)
                title = "提出物一覧"
                page = 0
                true
            }
            R.id.navigation_dotime -> {
                changePage(1)
                title = "DoTimeリスト"
                true
            }
            R.id.navigation_timetable -> {
                changePage(2)
                title = "時間割表"
                true
            }
            R.id.navigation_memorize -> {
                changePage(3)
                title = "暗記カード"
                true
            }
            R.id.navigation_others -> {
                changePage(4)
                title = "その他"
                true
            }
            else -> false
        }
    }

    fun changePage(to: Int) {
        main_view_pager.apply {
            scaleAnimate(0.92F, 80)
            alphaAnimate(0F, 80)
            Handler().postDelayed({
                main_view_pager.setCurrentItem(to, false)
                scaleAnimate(1F, 100)
                alphaAnimate(1F, 100)
            }, 80)
        }
    }

Functions.kt

fun View.alphaAnimate(to: Float, duration: Long) {
    val anim = ObjectAnimator.ofFloat(this, "alpha", to)
    anim.duration = duration
    anim.start()
}

fun View.scaleAnimate(to: Float, duration: Long) {
    val anim1 = ObjectAnimator.ofFloat(this, "scaleX", to)
    anim1.duration = duration
    val anim2 = ObjectAnimator.ofFloat(this, "scaleY", to)
    anim2.duration = duration
    anim1.start()
    anim2.start()
}

横スクロールのアニメーションをするのも禁止なので、setCurrentItemメソッドの「smoothScroll」の引数はfalseにします。後はそれっぽい感じにアニメーションさせます。

これで多分完成です。実際の動作は実際にアプリをダウンロードしてお試しください。↓

Google Play で手に入れよう

タグ:
navigation
コメントする

※コメントシステムの詳細はこちらを御覧ください。

コメント本文

※reCAPTCHAによるボット判定を行っているため、送信に少々時間がかかる場合があります。ご了承ください。

送信しました。

確認

コメントを削除しますか?

返信

返信を入力

arrow_upward