Visualaizerでアコーディオンメニューを作ってみる

## 目次
・はじめに
・実装方法
・実際に動かしてみる
・少し工夫を…

## はじめに
アプリやwebページを使用している時、
「ボタンを押すと対応するコンテンツが下に表示され、もう一度押すと非表示になる」
というアコーディオンメニューをよく見かけると思います。
今回の記事では、そのアコーディオンメニューを「kony visualizer」のバージョン9.3で実装してみようと思います。

## 実装方法
まずは使用するボタンなどのwidgetを配置していきます。
配置するものは
・メニューボタン(ボタン)
・メニューボタンに対応するコンテンツ(コンテナ + ラベル)です。
(ボタン、コンテナ、ラベルはDefaultLibraryにあるものを使用します。)
これを用意するメニューの数だけ配置していきます。
＜手順＞
　1.コンテナを配置
　　※「flxAccordion」と命名しました。
　　1-1.プロパティ→LookタブのWidth、Heightを100％、leftとtopを0にして配置します。
　　1-2.プロパティ→FlexContainerタブでLayoutTypeを「Flow Vertical」にします。
![コンテナ_プロパティ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/53c7e550-0363-c380-af90-c6289d4a98fd.png)
　2.手順1で配置したコンテナ(flxAccordion)の配下に各メニューを配置していきます。
　　2-1.コンテナを配置
　　　※今回は「flxAccordionMenu1」と命名しました。
　　　2-1-1.プロパティ→Lookタブを以下のように設定(座標については配置したい位置に変えていただいて大丈夫です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/f1c7fc9a-73e2-d9c3-f2e8-f7242a108c0c.png)
　　　2-1-2.このコンテナも同様にLayoutTypeを「Flow Vertical」にする(手順1-2参照)
　　2-2.手順2-1で配置したコンテナ(flxAccordionMenu1)の配下にメニューボタンとコンテナを順番に配置
　　　※座標は縦並びになるように、サイズはお好みで。(今回は一律、Width「300dp」Height「50dp」)
　　　※ボタンを「btnMenu1」、コンテナを「flxContent1」と命名しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/b56d7bf8-269d-37de-f126-30252c40fbbf.png)
　　2-3.手順2-2で配置したコンテナ(flxContent1)の配下にラベルを配置
　　　※WidthとHeightを100%にして親のコンテナと同じサイズ、leftとtopを「0」にして同じ配置になるよう設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/a33c562a-b2ff-395f-5882-ed1949af516e.png)
　　2-4.「flxAccordionMenu1」を必要な数だけ複製し、IDを編集していきます。(今回は3つ用意します。)
　　　2-4-1.「flxAccordionMenu1」を右クリック→「Duplicate」を選択
![右クリックメニュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/6732877a-0925-752c-a63b-e4cbcb15cde9.png)
　　　2-4-2.各ウィジェットのID、textを編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/c9b43ef6-94fe-27ea-1211-52f3cfb154a3.png)
これでウィジェットの配置は完了です！
___
次はフォームコントローラーに下記処理を記載します。

```js:Form1Controller.js
define({
  //引数にeventobjectを受け取る
  onClickBtn: function(obj){
    //idの末尾にある数字を取得
    var number = obj.id.slice(-1);
    //押されたボタンと同じ数字を持つflxContentの表示・非表示を切り替える
    this.view["flxContent" + number].isVisible = !this.view["flxContent" + number].isVisible;
  },
});
```
記載したら処理を各ボタンのアクションに紐づけていきます。(すべてのbtnMenuに紐づけます)
＜手順＞
　1.ボタンを選択して、プロパティ→Action→onClickの「Edit」をクリック
　2.画面左側の一覧から「InvokeFunction」を選択
　3.StartとEndの間に追加されるので、それをクリック
　4.画面右側に詳細が表示されるので、その中のFunctionNameで「onClickBtn」を選択
　5.続けて、InputParameters→ValueのEditを押下し、インプットパラメータの入力モーダルを表示
　6.EventObject→eventobjectの順に押下し、空白だったモーダルの上の部分に「eventobject」が入力されたことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/ca72be11-b004-43cd-2708-f71db0251c11.png)
　7.モーダルを閉じて、Saveボタンを押下

最後に現状表示されている、各flxContentを非表示にすることで完成です！！
![完成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/75a35fcc-2866-1e0a-e4eb-cf63130350a5.png)
## 実際に動かしてみる
実際にビルドして動かしてみましょう。
![動作確認.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/26246284-adc8-af15-2e1a-e7d41f38acf5.gif)
問題なく動作していそうですね！
## 少し工夫を…
現状でも使えますが、メニューの開閉が瞬間的に行われているので、もう少し滑らかに動かしたいです。
なのでメニューを開閉するときに、ゆっくり開閉するアニメーションを追加してみたいと思います！
ウィジェットの高さを時間かけて伸縮させることで、ゆっくり開閉するアニメーションを実現します。
＜手順＞
　1.各flxContentのVisibleをtrueにしてheightを「0」にする
　　→heightを0にすることで表示されない状態を作りだします。
![工夫.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/847efd6c-8908-614b-9d40-42c0201c007e.png)
　2.閉じる用のボタンをそれぞれ用意します。
　　2‐1.各「btnMenu～」をDuplicate
　　2-2.idを重複しないように変える(今回は「btnCloseMenu～」にしました)
　　　※末尾の数字は同じであること
　　2-3.Visibleをfalseにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/2b957050-4a4f-4d3c-a1a4-85f8da335af8.png)
　3.ソースを下記のように修正します。
　　※先ほどのソースでは開閉を同じメソッドで行っていましたがアニメーションを使い分けるために「開けるメソッド」、「閉じるメソッド」に分割します。

```js:Form1Controller.js
define({
  //引数にeventobjectを受け取る
  //開く処理
  onClickBtn: function(obj){
    //idの末尾にある数字を取得
    var number = obj.id.slice(-1);
    obj.isVisible = false;
    //閉じるボタンを表示
    this.view["btnCloseMenu" + number].isVisible = true;
    //押されたボタンと同じ数字を持つflxContentのheightを50dpにする
    this.view["flxContent" + number].animate(this.animateDefOpen(), this.animateConfig(), {});
  },
  //閉じる処理
  onClickCloseBtn: function(obj){
    //idの末尾にある数字を取得
    var number = obj.id.slice(-1);
    obj.isVisible = false;
    //開くボタンを表示
    this.view["btnMenu" + number].isVisible = true;
    //押されたボタンと同じ数字を持つflxContentのheightを0dpにする
    this.view["flxContent" + number].animate(this.animateDefClose(), this.animateConfig(), {});
  },
  //アニメーションの設定
  animateConfig: function(){
    var config = {
      "duration": 0.7,
      "iterationCount": 1,
      "delay": 0,
      "fillMode": kony.anim.FILL_MODE_FORWARDS
    };
    return config;
  },
  //開くアニメーション
  animateDefOpen: function(){
    var animDefinition =
        {
          "100": {
            "height": "50dp"
          }
        };
    var animDef = kony.ui.createAnimation(animDefinition);
    return animDef;
  },
  //閉じるアニメーション
  animateDefClose: function(){
    var animDefinition =
        {
          "100": {
            "height": "0dp"
          }
        };
    var animDef = kony.ui.createAnimation(animDefinition);
    return animDef;
  },
});
```

あとは手順2で作成したボタンに追加した閉じるメソッドを紐づけて完了です！
＜手順＞
　1.ボタンを選択して、プロパティ→Action→onClickの「Edit」をクリック
　2.StartとEndの間にある「InvokeFunction」をクリック
　　※「InvokeFunction」がない場合は左側の一覧から追加してください。
　3.画面右側に詳細が表示されるので、その中のFunctionNameで「onClickCloseBtn」を選択
　4.続けて、InputParameters→ValueのEditを押下し、インプットパラメータの入力モーダルを表示
　5.EventObject→eventobjectの順に押下し、空白だったモーダルの上の部分に「eventobject」が入力されたことを確認
　6.モーダルを閉じて、Saveボタンを押下

ビルドしてみると…
![動作確認_工夫.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/ce507d7f-63bf-9687-b9a8-95f4a62f16dc.gif)
上手く動きましたね！！
## まとめ
今回はVisualizerでアコーディオンメニューを実装する方法についてご紹介しました。
他にも工夫できる点はあると思うので、いろいろ試していただければと思います！
## 参考
https://qiita.com/Kony_Team/items/08c9f4ecaefb61d7ec6c