kivyMDチュートリアル其の参什漆 Components - NavigationRail篇

ハロー、Qiita。清秋の候、すがすがしい秋晴れの
今日この頃、いかがお過ごしでしょうか。

はいー、先週入れられてなかった時候の挨拶ですが、今週で使ってみました。
合ってますかね、使い方。

先日は地震などがありましたが、みなさんはご無事でしたでしょうか。常日頃、
備蓄などはしないといけないなと感じたくらい、身の危険を感じましたね。と、
いってもいざ事が起きたときは何も動けなかったのですが汗

というわけで、少し話は脱線しましたがKivyMDの時間は相変わらずオープン
します。今日は、NavigationRail編となります。

## NavigationRail

いざ始まるといっても、いつものリンクは飛ばすというのはありますが、今日は
少し重要なこともあるので何点か触れてみます。

2点ほどあるのですが、まずは他のナビゲーションと組み合わせてはいけないという
ことですね。他のナビゲーションとしては、先週やったNavigationDrawerともう
1つは以前やったBottomNavigationですね。これらと組み合わせると望ましくない
と書かれてあります。

もう1点は、デバイスの種類によって使い方を分ける必要もあるということが書かれて
います。具体的にはこちらのリンク箇所になりますね。

https://material.io/components/navigation-rail#behavior

この節の最下層である、「Responsive patterns」がまさに該当するところなの
ですが、この点にも注意が必要です。まずスマホタイプのデバイスでは、Navigati-
onDrawerかもしくはBottomNavigationを推奨しているところが注目ポイントです。

タブレットタイプはNavigationRailもしくはmodalタイプのNavigationDrawer、
デスクトップタイプはメニューバーが閉じていないNavigationDrawerという風に
それぞれ分けて作った方がよいよと推奨されていることも注意が必要そうです。

まぁ、要点としては今回のNavigationRailはタブレット向きということが分かり
ますね。\# 個人的にはデスクトップタイプも適しているかなぁとは思いますが

ということなので、今日はタブレットサイズを意識して結果の方を映していきたい
と思っております。

で、さらにマニュアルの方では以下のように概要が書かれています。

> Navigation rails provide ergonomic movement between primary destinations in apps.

ergonomicは翻訳を依頼しても「人間工学的に」と結果が返されましたが、その
可能性は多いに高いと思います。他の選択肢としては、生物工学とありますがそれは
ねーだろーというのが個人的見解です。これも個人的興味ですが、この分野はすごく
興味があるところです。また、テーマを取り上げてみようかな。

### Usage

少し前置きが長くなりましたが、使用方法についてさっそく入っていきます。

```python
MDNavigationRail:

    MDNavigationRailItem:

    MDNavigationRailItem:

    MDNavigationRailItem:
```

特に難しいということはなさそうですね。実は言うと、この形は初出ではありません。
もう分かっているよという方もいらっしゃるかもしれませんが、そうです、ImageList
篇でやりましたね。全然そんなこと知らないよという方は以下もしくはマニュアルをご覧
頂ければ。

https://qiita.com/virty/items/c473db997d1e215e252a

使い方が分かったところで、さっそく動かしていきましょう。下記のコードはマニュアルから
ほとんど変更はありません。

```python:xxxvii/navigation_rail.py
from kivy.factory import Factory
from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
#:import get_color_from_hex kivy.utils.get_color_from_hex


<MyTile@SmartTileWithStar>
    size_hint_y: None
    height: "240dp"


MDBoxLayout:
    orientation: "vertical"

    MDToolbar:
        title: "MDNavigationRail"
        md_bg_color: rail.md_bg_color

    MDBoxLayout:

        MDNavigationRail:
            id: rail
            md_bg_color: get_color_from_hex("#344954")
            color_normal: get_color_from_hex("#718089")
            color_active: get_color_from_hex("#f3ab44")

            MDNavigationRailItem:
                icon: "language-cpp"
                text: "C++"

            MDNavigationRailItem:
                icon: "language-python"
                text: "Python"

            MDNavigationRailItem:
                icon: "language-swift"
                text: "Swift"

        MDBoxLayout:
            padding: "24dp"

            ScrollView:

                MDList:
                    id: box
                    cols: 3
                    spacing: "12dp"
'''


class Test(MDApp):
    def build(self):
        return Builder.load_string(KV)

    def on_start(self):
        for i in range(9):
            tile = Factory.MyTile(source="好きな画像を入れてみるとおもしろいよ!")
            tile.stars = 5
            self.root.ids.box.add_widget(tile)
```

全てコードを載っけてみると、なにやら難しそう...と思われる方がいらっしゃる
かもしれませんが、これまでKivyMDのコードをいっぱい見てきた方はなんだか変わ
ったことねーなと思われるかもしれません。カスタムレイアウトのところなんかは、
まさにImageList篇でやったところですしね。

といっても慣れてない方はなんのこっちゃとなりますので、前提知識となるリンクを
載っけておきます。これらを見てから、こちらに戻ると見る景色が変わってくるかと
思われます。

https://qiita.com/virty/items/d5fa0a529912e6b0beb0

https://qiita.com/virty/items/3871b85bc67179d67b30

https://qiita.com/virty/items/3c726e2a7faa694fb54d

https://qiita.com/virty/items/b16b4aaf23956493e1d7

まぁ、これらが分かりにくいんだよ!という方はマニュアルを見てもらえればと思い
ます。あと、NavigationDrawer篇を入れている理由としては、レイアウトの実装
する形が似ているからになりますね。メインコンテンツとメニューバーらしきものを
分けているということは共通するところだと考えています。

今回新出のプロパティとかはAPIのところで触れますのでご安心を。あとは漏れている
ところですが、MyTileをFactoryしている画像などは好きなものを入れてあげてくだ
さい。詳しく仕様を見ているわけではありませんが、よく使われている拡張子はほとんど
対応しているはずです。

### 結果

ということで、サクサクと触れ込みは終わりましたが、論より証拠ということで
実行結果の方に移りたいと思います。特に動きとかは変わったことないので、画像
キャプチャでお送りします。

![174.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/623dc612-3181-772a-b2ce-a99f9cb63b19.png)

動作自体も問題はなさそうでヨシ!という感じですね。今回使った画像は前回同様、以下
サイトから拝借しました。

https://kumamine.blogspot.com/2019/12/blog-post_27.html

メニューバーらしきものと全然関わりがないですが、それぞれの言語で案件を募集して
いる猫を探すと、このような画面になりそうですね(意味不明)。

### Extend Usage

少しこのまま終わるのは寂しい気もしますので、もう少し触ってみます。といっても
マニュアルのものからそれほど大きくはハズレはしませんが。。

どんなことをやったかを簡単に説明しますと、もう本当に簡単に言えばAPIでコードなり
キャプチャがあるところを実装してみただけになります。まぁそれだけっちゃそれだけ
なのですが、思わぬ収穫もあったりで。。

コードについても全て載せても良いのですが、ほとんどベースとしてはUsageのところで
やったものなので差分なりを載せておきます。

```python:xxxvii/extend_navigation_rail.py

(略)

    MDToolbar:
        title: "MDNavigationRail"
        md_bg_color: rail.md_bg_color
        left_action_items: [["menu", lambda x: app.rail_open()]]

    MDBoxLayout:

        MDNavigationRail:
            id: rail
            # item text selected
            visible: "Selected"
            # menu( item) color
            md_bg_color: get_color_from_hex("#407294")
            color_normal: get_color_from_hex("#e6e6fa")
            color_active: get_color_from_hex("#e2d0ca")
            # hover
            use_hover_behavior: True
            hover_bg: 1, 1, 1, .2
            # rail open/close
            use_resizeable: True
            # title
            use_title: True
            icon_title: "./genba_neko.png"
            text_title: "[b][color=#ffffff]Example[/color][/b]"
            # action button
            use_action_button: True
            action_text_button: "COMPOSE"
            on_action_button: print(args)

(略)

    def rail_open(self):
        if self.root.ids.rail.rail_state == "open":
            self.root.ids.rail.rail_state = "close"
        else:
            self.root.ids.rail.rail_state = "open"

(略)

```

はい、省略が多いですが、上記のようになっております。まずkv側とクラス側ある、
rail_openコールバックメソッドですが、これはツールバーのハンバーガーメニュー
で開閉されるメニューバーの実装となっています。これ以上長ければこのままでも
よさそうですが、単にif-elseであればkv側でまとめてもよさそうですね。

次のまたkv側に戻り、MDNavigationRailで定義しているプロパティですが、コメ
ントにも書いてる通りAPIで書かれているものを使用しています。詳細はAPIの方に
お譲りしますというか私が引き受けるんですけどね。簡単に言えば、先ほどはメニュ
ーバーがなかったりアカウント画像がなかったりしていましたが、このコードではそれ
らが追加されています。

### 結果

はい、まぁうだうだ言っても、実行結果を見るに越したことはないので先に見てしまい
ましょう。

![175.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/df521241-7ecc-1bcc-059e-eeacbd7dad50.png)

![176.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/cf9b2f30-1487-00ae-4c1b-964630a9c045.png)

![177.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/c2158668-1789-4117-974b-ba4e20f09ab4.png)

今回も画像ギャラリーということで、マスコットキャラクター(?)のSayaさんに登場
いただきました！もうKivyMDというとこの方しかいませんね！(勝手な決めつけ)

動かしたものも特に問題はないですね、って言いたいところですが問題ありますね。
アクションボタン(黄色いプラスボタン)のテキストなんかは見えていないことが
わかっています。あとは、hoverの振る舞いなんかも適用されていないことも
分かりました。その他は特に問題なしだったかと。

すみません、動画だと動きが分かりやすいというのはあるんですけど、なぜか制限
が掛かっちゃってアップができませんでした。。一旦は画像の方でお許しを。

テーマに関しては少し変えてみたというのはありますが、色のことについては
ど素人なので、以下を参考にして決めてみました。

https://www.color-hex.com/

### API - kivymd.uix.navigationrail.navigationrail

ということで、少し触れ込みを端折ったプロパティなどもあるので、もうこちらに入り
ます。

#### class kivymd.uix.navigationrail.navigationrail.MDNavigationRailItem(**kwargs)

アイテムとあるので、こちらはメニューアイテムらしきところでしたね。Pythonだとか
設定したやつになります。

`icon`

> Icon item.

> icon is an StringProperty and defaults to ‘checkbox-blank’.

`text`

> Text item.

> text is an StringProperty and defaults to ‘’.

これらが今回使用したものになります。それぞれデフォルトで持つものが変わりますね。

`set_width(self, interval: Union[int, float])`

> Sets the size of the menu item.

横幅は変えられないのかなと思っていましたが、どうやら変えれそうですね。でも、
試すまではできませんでした汗 どうなるか試してもらい、コメント頂けると嬉しい
です。

#### class kivymd.uix.navigationrail.navigationrail.MDNavigationRail(**kwargs)

`use_hover_behavior`

> Whether to use the HoverBehavior effect for menu items.

`hover_bg`

> The background color for the menu item. Used when use_hover_behavior parameter is True.

動かなかったやつですね。次回のバージョンに期待です。Todoが重なっていくよぅ。。

`use_resizeable`

> Allows you to change the width of the rail (open/close).

> use_resizeable is an BooleanProperty and defaults to False.

railを開閉するためにはこちらを有効化する必要があるようです。ちなみにExtendの
コードはここから持ち出しました。まぁUsageからそれほど変化はありませんが。。

`use_title`

> Whether to use an additional panel at the top of the rail.

> use_title is an BooleanProperty and defaults to False.

`icon_title`

> Icon (name or path to png file) for NavigationRailTitle class.

> icon_title is an StringProperty and defaults to ‘menu’.

`text_title`

> Text title for NavigationRailTitle class.

> text_title is an StringProperty and defaults to ‘Rail’.

タイトルに関するものですね。こちらはちゃんと反映がされました。先述したアカウント
画像はここのアイコン(icon_title)を指し示していました。

`use_action_button`

> Should MDFloatingActionButton button be used.

> use_action_button is an BooleanProperty and defaults to False.

`action_icon_button`

> Icon of use_action_button.

> action_icon_button is an StringProperty and defaults to ‘plus’.

`action_text_button`

> Text of use_action_button.

> action_text_button is an StringProperty and defaults to ‘’.

アクションボタンにまつわるものです。残念ながら、action_text_buttonは有効化
されませんでした。

`color_normal`

> Color normal of item menu.

> color_normal is an ColorProperty and defaults to None.

`color_active`

> Color active of item menu.

> color_active is an ColorProperty and defaults to None.

ここは分かりにくいところですが、単にメニューアイテムを押す前後の色指定になり
ますね。normal/active(選択されていない/されている)という風に分けられてい
ます。これだと、説明いらないか。

`visible`

> Item label visible type. Available options are: ‘Selected’, ‘Persistent’, ‘Unlabeled’.

> visible is an OptionProperty and defaults to ‘Persistent’.

こちらは、説明通りということになるでしょうか。Extendでは、‘Selected’に設定
して選択したときにラベルを表示していました。

`rail_state`

> Closed or open rails.

> rail_state is a OptionProperty and defaults to ‘close’.

コールバックメソッドと一緒に使われるものですね。単にkv側だけでも済ませられ
そうなところです(2回目)。

## まとめ

さて、いかがだったでしょうか。

先週のナビゲーションドローワーと言い、使いこなすのは難しいですが慣れてくると
強力なコンポーネントとなることは間違いないでしょう。

使用するデバイスはタブレットタイプと若干制限が強いですが、専用アプリを作ると
決めてしまえばなかなか心強いのではないでしょうか。頑張ればNetFlixなんかの
クローンも作れそうな勢いです。

正直、メニューアイテムの選択でどうやってコンテンツの使い分けをするのだろう
という疑問はあるのですが、今後の課題となりそうです。余裕があれば、実現できる
よう取り組みます。そのときが来たら、頑張ってみます。

ということで今週はここまでで。来週はPickers篇に入ろうかと思っていましたが、
コンポーネンツの構成が変わったり、前回触れられていないところは0.104.2でも
動かないというように時期尚早な状況です。一旦バージョンアップ後ですね、動かす
のは。

なので、1つ飛ばしてSelection篇になりますね。ということで来週もお楽しみにー。

それでは、ごきげんよう。

## 参照

> Components » NavigationRail
> https://kivymd.readthedocs.io/en/latest/components/navigationrail/

> DeepL 翻訳ツール
> https://www.deepl.com/ja/translator

> 「そろそろ時間だから行こっか」のフリー素材
> https://www.pakutaso.com/20160452095post-7493.html