kivyMDチュートリアル其の捌 Components - Banner篇

さぁ、今週もやって参りました！kivyMDのお時間です。
いかがお過ごしでしょうか。

ようやく、緊急事態宣言も今週で解除となりそうですが心がウキウキしてきますね。
桜もそろそろ咲いてくるかなという感じなので、人で街が溢れかえりそうです。
みなさんはどこか遠くへお出かけの予定はあるといった感じでしょうか。私は特に変わらず
といった次第です。。

## Banner

はい、ここも同様です。マテリアルデザインの方のリンクがあるので興味がある方は
リンクを読んでもらえればと思います。こういった使い方をするんだよーとかが書いて
あるので、実際に使うときは重宝するかもしれません。

リンクの方のサンプルとしては、アプリ使用時にログインIDなどが変更された場合に
画面上部にバナーを表示されるといったシナリオが想定されています。あまりこういった
場面に遭遇したことはないので、実感が湧かないのですがもし出くわした方がいらっしゃい
ましたらコメントいただけると嬉しいです。

### Usage

使用方法としてタイトルが付けられていますが、実際はご丁寧にサンプルコードが載せられて
います。少し動かなかった部分もあるので、カスタムしたコードを以下に載せます。まずは実際
に論より証拠をということでコードを見ていきましょう。

```python:viii/banner.py
from kivy.lang import Builder
from kivy.factory import Factory

from kivymd.app import MDApp

Builder.load_string('''
<ExampleBanner@Screen>

    MDBanner:
        id: banner
        text: ["One line string text example without actions."]
        
        # two-line
        #type: "two-line"
        #text:
        #    ["One line string text example without actions.", "This is the second line of the banner message."]
        
        # three-line
        #type: "three-line"
        #text:
        #    ["One line string text example without actions.", "This is the second line of the banner message.", "and this is the third line of the banner message."]

        # one-button
        #text: ["One line string text example without actions."]
        #left_action: ["CANCEL", lambda x: None]
        
        # two-buttons
        #text: ["One line string text example without actions."]
        #left_action: ["CANCEL", lambda x: None]
        #right_action: ["CLOSE", lambda x: None]
        
        # one-line with icon
        
        #type: "one-line-icon"
        #icon: f"{images_path}kivymd_logo.png"
        #text: ["One line string text example without actions."]
        
        # The widget that is under the banner.
        # It will be shifted down to the height of the banner.
        over_widget: screen
        # vertical_pad: toolbar.height

    MDToolbar:
        id: toolbar
        title: "Example Banners"
        elevation: 10
        pos_hint: {'top': 1}

    BoxLayout:
        id: screen
        orientation: "vertical"
        size_hint_y: None
        height: Window.height - toolbar.height

        OneLineListItem:
            text: "Banner without actions"
            on_release: banner.show()

        Widget:
''')


class Test(MDApp):
    def build(self):
        return Factory.ExampleBanner()


Test().run()
```

今回もMDAppを継承しているTestクラス側などは省略します。
ここも生成方法など様々で一定ではありませんが、特筆することもないので一旦パスを。

#### ExampleBanner@Screen

今回のメインであるMDBannerを中心に触れ込んでいきたいと思います。

まずExampleBannerウィジェットですが、こちらはScreenを継承させていますね。
Components全てそうかは分かりませんが、以下の1文を読み込むだけで使用する
ことができます。

```
from kivymd.app import MDApp
```

本当にこの辺りは、サンプルでは一貫性がなく柔軟にかけるよーということを示唆
しています。まぁ、そんなことは置いておいて中身の方をじっくり見ていきます。

##### MDBanner
はい、早速やってきました。今日のメインコンポーネントです。あ、先に言っておきますが
MDToolbarについては今度の機会でということと、BoxLayoutはバナーとリンクしている
ということで今日の触れ込みはバナーだけということになります。

まずはidになりますが、これは触れ込む必要はありませんね。気になる方がいらっしゃいま
したら過去のページでもご覧いただければと思います。続けてはtextになりますが、ここは
バナーのテキストでtypeとリンクしやすいところなので同時に触れ込みます。まず仕様として
は以下になります。

`text`

> List of lines for banner text. Must contain no more than three lines 
> for a ‘one-line’, ‘two-line’ and ‘three-line’ banner, respectively.

> text is an ListProperty and defaults to [].

`type`

> Banner type. . Available options are: (“one-line”, “two-line”, 
> “three-line”, “one-line-icon”, “two-line-icon”, “three-line-icon”).

> type is an OptionProperty and defaults to ‘one-line’.

2つがメインのメインになります。まずtextですが、こちらは文字列ではなくリストプロパティ
となります。表示させたい項目が複数あるときのためにこのようになっています。複数といっても
3行までという制限はありますけどね。

そして続けて、typeとなります。こちらはバナータイプとそのままかいとツッコまれそうですが
先ほどのtextをどのように表示させるかを指定するためにあります。どういうことかというと、
鋭い方は感づきそうですが複数表示かはたまたアイコン付きの表示かとか、バナーは色々選択
出来るようです。上にある通り、テキストだけの1~3行表示とアイコン入りのテキスト1~3行表示
と計6つのバリエーションがあります。デフォは1行表示となります。コードの方では全て列記して
いませんがマニュアルでキャプチャがあるものは記載しておきましたので、適宜コメントアウト
しながら確かめるとほーんとなるかもしれません。

まだ、こちらは終わりではありません。って途中で終わっているので当たり前ですが。
なんとこのバナー、右下あたりにボタンのようなアクションを取り込めるようにもなっています。
仕様を以下に書いておきます。


`left_action`

> The action of banner.
> To add one action, make a list [‘name_action’, callback] 
> where ‘name_action’ is a string that corresponds to an action name 
> and callback is the function called on a touch release event.

> left_action is an ListProperty and defaults to [].

`right_action`

> Works the same way as left_action.

> right_action is an ListProperty and defaults to [].

両方同じようなものなので、left_actionだけ触れ込みます。こちらもまずtextみたいに
リストプロパティで、アクションの名前とコールバックを入れ込む形となります。なんで
辞書プロパティではないんだろう。このコールバックに例えば「ログイン」という名前だと
実際のログイン画面に遷移する関数を呼び出すように指定する必要があります。

right_actionも同じように指定する必要があります。当然こちらもリストプロパティ。
まぁ、わかるかと思いますがただアクションを左右どちらかに表示させるかという違いしか
ないということでしょうか。

あとは、コードの方に戻りますがover_widgetというものもあります。
こちらの仕様は以下の通り。

`over_widget`

> The widget that is under the banner. It will be shifted down to the height of the banner.

> over_widget is an ObjectProperty and defaults to None.

こちらはオブジェクトプロパティでどのウィジェットを指定してその上側に表示させるか
ということになります。そのウィジェット自体は下に下がっちゃいます。今回でいうと
BoxLayoutがまさしくウィジェットに該当しますね。

あとはvertical_padですが、こちらも仕様は以下の通り。

`vertical_pad`

> Indent the banner at the top of the screen.

> vertical_pad is an NumericProperty and defaults to dp(68).

こちらは数値のプロパティでデフォルトはdp(68)とあります。インデントとそのまま訳すと
確かにコードのインデントとよく似ているところです。どういうことかというと、先ほどover
_widgetのところで指定したウィジェットが下がると述べました。そこで下がった分領域が確保
されますが、その領域と言えますでしょうか。んー、説明が難しい。とりあえず触れ込みはそんな
ところで、実際に数値を入れた適当な様子を見てもらった方が早そうです。

![25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/a47ccead-89c0-a7f0-0abb-d256eef5f545.png)

んー、これはお粗末すぎる。。見事にレイアウトが崩れていますね。デフォルトとか数値を
決めて指定するよりかは、指定されている通り最上部(ここではMDToolbar)のウィジェット
の高さを指定すると良さそうです。

##### BoxLayout

はい、不言実行ですね。さっき触れ込みはMDBannerだけと言ってましたが、気になるところ
もあるので一応少しだけ。基本的には目新しいものはないですが、heightと中で持っている
OneLineListItemのon_releaseは認識しておきたいところです。

heightはBoxLayoutをどこに表示させるかという位置の指定ですが、ここでは以下のように
することで自動で配置しています。

```
Window.height - toolbar.height
```

on_releaseについてはOneLineListItem側でon_releaseアクションがなされたときに
以下のようにMDBannerを出すようにしています。

```
banner.show()
```

ログインIDが変更された際の検出とかも同じようにする必要があります。

コード上の触れ込みは以上になります。

### API - kivymd.uix.banner

####  class kivymd.uix.banner.MDBanner(**kwargs)

さぁ、終わりーと一息つきたいところですが気になったのでクラスの定義で書かれている
ところを翻訳依頼してみました。結果はというと、よくわかんねと言えばそこまでなのですがw
少し触れ込んでいくと、ウィジェットの読み込みを最適化(ここでは時間短縮)してくれるのが
FakeRectangularElevationBehaviorということなのでしょうか。

クラス定義で引数にこれを指定するのだよーと言われてるのですが、これはkv側で定義する
ときはどうすりゃいいの？と質問したくなります。あまりこれ以上触れ込めないので以上という
ことでw また実際にパフォーマンス上がるかとかは時間ある際に〜

## 結果

ここでは、アイコン入りの1行表示のバナーを載せておきます。
すでに結果出たとこもありましたが。。あ、Usageのところのコードを試した挙動ではないので
悪しからず。mac環境だからか、そのままマニュアルのコードを動かすと動かない事象もあったので
変更したところをということで載せています。コード上だと「one-line with icon」とコメント
アウトしたところになります。

![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/d3b81f1b-33f3-e6f1-6e8d-411c1e5cc382.png)

## まとめ

さぁ、いかがだったでしょうか。少し使いどころが限定されるのは否めないでしょうが
使い方次第ではユーザー体験がうんと上がりそうなバナーを触れ込みました。じゃあ、
お前はどう使うのよと言われるとアワワワと慌てふためきそうですが、ユーザーの待機
時間が結構あるときに楽しんでるー？とかバナーを出してみても良いかもしれません。
えぇぇ、どんな使い方よと言われそうですが、もしこんな使い方はどうよ？というのが
ありましたら、コメント頂けると幸いです。では時間も良いところなのでこの辺で。

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

## 参照

> Components - Banner

> https://kivymd.readthedocs.io/en/latest/components/banner/