kivyMDチュートリアル其の弍什玖 Components - Spinner篇

こんにちは！(急にシンプル)

みなさん、いかがお過ごしでしょうか。
今週も暑かったですね。と思ったら台風が近づいて、涼しくなったりして
体調崩しやすくなので嫌になったりしますね。

今週は佳境期なのか分かりませんが、オリンピックの話題が多かったでしょうか。
まさか選手以外で金メダルを噛む方が存在するとは・・・と若干引いてはいましたが、
良し悪しに限らず盛り上がることは良いことではないでしょうか。知らないけど。

とまぁ、世間は盛り上がっているのかいないのか全然温度感は分かりませんが、
我々はプログラミングの金メダルを取れるようにしていきたいものですね！(意味不明)
取った暁には噛んで自己満足しましょう。そして誰かが取った場合にはそれを噛んでやり
ましょう。(暑さのおかげで頭がオーバーヒート起こしています)

というわけで日々励んでいけばいつか良いことがということを夢見て、今日も元気に
kivyMDチュートリアルをやっていきます。今日はSpinner篇となります。

## Spinner

https://material.io/components/progress-indicators#circular-progress-indicators

とまぁ、いきなりなんの意図があるんだ・・と見慣れない方は思うかもしれませんが、
いつも見られている方は「いやそんな横着しなくても」と思うかもしれません。という
か、思って欲しい!という願望は置いておいて、リンク見てよねという思いがあります。

まぁ、私がいうまでもないかもしれませんが、これは見たことがある方が多いかもしれ
ません。あの待っているときにグルグルしているものになります。似たようなものだと
ProgressBarなどがあって、主に計測可能なタスクがありその進捗を見れるようにする
のが常例ですが、Spinnerは少しテイストが異なります。これは現状あとどのくらいか
ということは見えるわけでもありません。少し待ってねという意思表示のみになります。

と言ってもこの後に出てくる、Determinate modeでは必ずしもその通りでもないこと
が伺えます。MaterialDesignのリンク先では、これがGooglePlayなどで代表される
もので、アプリでダウンロードするときに見られるものが例にあります。ダウンロード
するときに落としているときに、ステータスが見れる輪っか状のものもありますよね。
あれがDeterminate modeで使われているような紹介がありました。

結論ややこしくなってきましたが、要はProgressBarと合わせると進捗管理するコンポ
ーネントだよーと覚えておいてもよいのではないでしょうか(大どんでん返し)。ちなみに
マニュアル上では、このような記載がありました。はっきりprogress(進捗)と書いてい
ますね。

> Circular progress indicator in Google’s Material Design.

というわけで、前置きが長くなってしまいましたが、論より証拠ということで実際にコード
と実行結果を見てみましょうか。まずはコードからになります。

### Usage

```python:xxix/spinner.py
from kivy.lang import Builder

from kivymd.app import MDApp

KV = '''
MDScreen:

    # Indeterminate mode
    MDSpinner:
        size_hint: None, None
        size: dp(46), dp(46)
        pos_hint: {'center_x': .3, 'center_y': .5}
        active: True if check.active else False

    # Spinner palette
    MDSpinner:
        # The number of color values can be any.
        size_hint: None, None
        size: dp(46), dp(46)
        pos_hint: {'center_x': .5, 'center_y': .5}
        palette:
            [0.28627450980392155, 0.8431372549019608, 0.596078431372549, 1], [0.3568627450980392, 0.3215686274509804, 0.8666666666666667, 1], [0.8862745098039215, 0.36470588235294116, 0.592156862745098, 1], [0.8784313725490196, 0.9058823529411765, 0.40784313725490196, 1],
        active: True if check.active else False

    # Determinate mode
    MDSpinner:
        size_hint: None, None
        size: dp(46), dp(46)
        pos_hint: {'center_x': .7, 'center_y': .5}
        determinate: True
        active: True if check.active else False

    MDCheckbox:
        id: check
        size_hint: None, None
        size: dp(48), dp(48)
        pos_hint: {'center_x': .5, 'center_y': .4}
        active: True
'''


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


Test().run()
```

少し長くマニュアルから色々改変しているのかと思われるかもしれませんが、なんてこと
ないただただ小分けされていたものをくっつけただけになります。イメージなどは実行結果
とかを見てもらえれば。

#### kv側

今回はこれがメインディッシュでもあり唯一の触れ込みになります。import文だとか
クラス側では特にとりとめもありません。

そしてkv側も特に大きく変わりがあるかと言われると、それほど変わりもありませんが
新しくSpinnerを触れ込むということで、そこを中心に触っていきます。

まずはMDScreen配下に定義されているそれぞれのMDSpinnerを触れていきます。少し
分かりやすく共通の定義がどうなっているかを以下に抜粋しておきます。

```python
~

(略)

KV = '''
MDScreen:

    # common setting in Spinner
    MDSpinner:
        size_hint: None, None
        size: dp(46), dp(46)
        pos_hint: {'center_x': .N※, 'center_y': .5}
        active: True if check.active else False
    ※ ここは配置を分けているので配置させたいそれぞれの値が入る

~

'''

(略)
```

まとめてみるとスッキリしますね。size_hintやsize、pos_hint、activeプロパティ
などは実は共通の設定となっていました。size_hintやsize、pos_hintプロパティなど
は他で取り扱っているのでそちらでご参照を(Layout篇とか)。pos_hintプロパティの
x座標の値はそれぞれ異なっているのでそれだけご注意ください。

あとは新出のactiveプロパティですが、これは後ほど出てくるチェックボックスのフラグ
によって出現させるかのプロパティになります。ifワンライナー文が値に入っていますね。

さぁ、共通部分は分かりましたが、どうやってそれぞれのモードを使い分けるのでしょうか。
先程のコードから追記をします。

```python
~

(略)

KV = '''
MDScreen:

    # common setting in Spinner
    MDSpinner:
        size_hint: None, None
        size: dp(46), dp(46)
        pos_hint: {'center_x': .N, 'center_y': .5}
+       # Spinner palette
+       palette:
+           [...],[...],...
+       # Determinate mode
+       determinate: True
        active: True if check.active else False

~

'''

(略)
```

先頭行頭に+で記載があるのが、追記項目になります。paletteモードはpaletteプロ
パティがくっ付いていますね。詳細はAPIに譲りますが、カラー値のリスト型を値として
埋め込みます。

Determinateモードではそのままプロパティがくっ付いていますね。こちらはT/Fの
フラグが中に入ります。Trueにしなければ有効となりません。

触れてはいませんが最初のコードにある、Indeterminateモード(勝手に言っている)
はどちらも無くしたというか定義していない設定がそうなると思ってもらった方がいい
ような気もします。イメージ的にはデフォルトというか。

最後に、チェックボックスはどうなっているか見てみましょう。

```python
MDCheckbox:
    id: check
    size_hint: None, None
    size: dp(48), dp(48)
    pos_hint: {'center_x': .5, 'center_y': .4}
    active: True
```

size_hintやsize、pos_hintなどは先ほどと同じですね。変わっていることとすれば、
idとactiveプロパティになります。idを「check」と定めて、MDSpinner側のactive
プロパティでcheck.activeというふうにデータバインディングが出来るようidプロパティ
を定めています。Spinner側でのactiveは実質MDCheckboxのactiveフラグになりますね。

### API - kivymd.uix.spinner

####  class kivymd.uix.spinner.MDSpinner(**kwargs)

というわけでいきなり実行結果に入りたい気持ちはやまやまですが、使用したAPIを触れて
おきます。なにやら長々と説明文があるので、こちらでも記載はしておきます。

> MDSpinner is an implementation of the circular progress indicator 
> in Google’s Material Design.

> It can be used either as an indeterminate indicator that loops 
> while the user waits for something to happen, or as a determinate indicator.

> Set determinate to True to activate determinate mode, and determinate_time 
> to set the duration of the animation.

とりとめとしては、determinateモードのときに時間を定めることができるという
ことでしょうか。この後で、そのプロパティも触れておきますね。

`determinate`

> Determinate value.

> determinate is a BooleanProperty and defaults to False.

いうまでもないですね。デフォルトはFalseとなって有効化はされません。

`determinate_time`

> Determinate time value.

> determinate_time is a NumericProperty and defaults to 2.

先程出てきたものですね。デフォルトは2秒なのかな。

`active`

> Use active to start or stop the spinner.

> active is a BooleanProperty and defaults to True.

これも先述の通りですね。デフォルトはTrueです。

`color`

> Spinner color.

> color is a ColorProperty and defaults to [0, 0, 0, 0].

paletteモードでもカラーは選べましたが、そもそもの色も選べるようです。
ただし試しに動かしたときに、チェックを2回ほど押したときに色が変わったりして、
少し発展途上感も否めませんでした。

`palette`

> A set of colors. Changes with each completed spinner cycle.

> palette is a ListProperty and defaults to [].

こちらも言わずもがなかもですね。ですが、あまりさっき触れてなかったですが、
後でも分かることで結構発展途上感があります。有効化された試しがないという。。

### 結果

さて、お疲れ様でした！(まだ終わってない)

はやく終わるかなと思いましたが、結構今日も時間が掛かっています・・・
という、どうでもよいことはいいので早速結果の方に移ります。今日もgif形式で
お届けします。

![138.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82826/c52d93f7-c09c-566c-bebb-fa4189e7082c.gif)

少しgifがもっちゃりしているだけで、実際はこんなにもっちゃりしているわけでは
ありません。

左からIndeterminate、Palette、Determinateモードの順になります。
先に留意事項から言うと、Paletteモードでは有効化されていませんね・・・全然
色が変わっていません。

その他はマニュアルとほぼ変わりありませんが、Determinateモードに関しては
最初の動きが少し変わっているような気もします。Googleの正式なモードを参照
できていないのでなんとも言い難いですが・・・

チェックボックスとの連携も問題ありませんね。ちゃんとOffったときには表示され
ない仕組みとなっています。

## まとめ

はい、以上になります！(圧倒的開放感)

Indeterminateモードとかは問題なく使用できるかもですが、他は注意点が必要
になるかもしれません。使用するときには要検証項目になりそうです。まぁ試すの
はあたり前っちゃあたり前ですが。

次バージョンでどのように振る舞いが変わるかとかは関心度が高いですが、これらは
時間があるときは見ていきたいと思います。

ということで、今日は以上になります！来週はもうすでにやっていることと動かない
ことがありで、TapTargetView篇になります。あくまで順番通りっちゃ順番通りに
なります。では、再々ですがお疲れ様でした！

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

## 参照

> Components » Spinner
> https://kivymd.readthedocs.io/en/latest/components/spinner/