Kotlin 動的レイアウトのあれこれ

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-178389954-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-178389954-1');
</script>


#はじめに
今回は動的レイアウトについてです。重複するデザインがたくさんあり、XMLで記述するの面倒くさいので動的レイアウトで画面を作っていこうと思いところどころうまくいかないことがあったのでメモで残しておきます！
コピペ大歓迎ですが、誤字脱字があるかもしれません。ご注意を...//

##開発環境
- iMac 2019モデル Big sur(BootCampでWindowsを使用しています。)
- 32GBメモリ
- Android Studio
- kotlin

#本題

- TextView編
- LayoutParams編
- LinearLayout編
- 動的レイアウトの作成例

の順番で紹介していきます
では、さっそいくみていきましょう！
## -TextView編
**基本的な使用方法**

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_result_view)

        val textView:TextView = TextView(this)
        textView.text = "hogehoge"
        ~~~.addView(textView)
}
```
１行目でTextViewのインスタンスを生成し、２行目で文字列を代入し、３行目で何かのViewやLayoutに対してaddViewをしています。たったこれだけで画面上にhogehogeと表示することが可能です。通常これだけ使うことは有り得ないですね！

以下その他のプロパティの設定です。よく使いそうなものだけ紹介します！

```kotlin:MainActivity.kt
    val textView:TextView = TextView(this)
    textView.textSize = 5F    //文字サイズの変更（Float型）
    textView.setTypeface(Typeface.DEFAULT)    //文字タイプの設定(DEFAULT,BOLD,ITALIC,BOLD_ITALIC...)
    textView.layoutParams = LayoutParams      //文字のレイアウト設定、後程紹介します
    textview.gravity = Gravity.CENTER         //文字の配置場所の設定です(CENTER,RIGHT,LEFT...)

```
また、

```kotlin:MainActivity.kt
    val textView:TextView = TextView(this).also {
        it.textSize = 5F
        it.setTypeface(Typeface.DEFAULT)
        it.gravity = Gravity = Gravity.CENTER
    }
```
`.also`を使用してこのように書くこともできます！
ここらあたりがよく使いそうですね('_')
ぜひ使い方をマスターしましょう！

## -LayoutParams編
TextView編ででてきたLayoutParamsを紹介します
**基本的な使用方法**

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_result_view)

        val textView:TextView = TextView(this)
        val WC = LinearLayout.LayoutParams.WRAP_CONTENT
        val LP = LinearLayout.LayoutParams(WC,WC)
        textView.layoutParams = LP
}
```
このように書くと

```xml:activity_main.xml
<!--<LinearLayout>-->
    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content">
<!--</LinearLayout>-->
```
と同じになります！さらに、Marginの設定もlayoutParamsを使用して設定します。

```kotlin:MainActivity.kt
    val textView:TextView = TextView(this)
    val WC = LinearLayout.LayoutParams.WRAP_CONTENT
    val MLP = LinearLayout.LayoutParams(WC,WC)
    textView.layoutParams = LP
    val MLP = textView.layoutParams as ViewGroup.MarginLayoutParams
    MLP.setMargins(0,0,10,0)       //(left:,top:,right:,bottom)の順番
    textView.layoutParams = MLP    //反映
```
Padding反映されないなって方はMarginしちゃいましょう（苦）
部品の配置系はこのように変更するので結構よく使います！

## -Layout編
LinearLayoutを使用して紹介します。(たぶん他もあまり変わらないはず、、、)
**基本的な使用方法**

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_result_view)

        val scrollView:ScrollView = findViewById(R.id.ScrollView)    //ScrollViewが配置されていたとする

        val WC = LinearLayout.LayoutParams.WRAP_CONTENT
        val LP = LinearLayout.LayoutParams(WC,WC)
        val linearLayout = LinearLayout(this).also{    //orientationを省略するとデフォルトのHORIZONTALが採用される
            it.orientation = LinearLayout.VERTICAL
        }
        
        val textView:TextView = TextView(this)
        textView.text = "hogehoge"
        linearLayout.addView(textView)

        scrollView.addView(linnearLayout)    //ScrollViewに反映する
    }
}
```
以下その他のプロパティの設定です。僕が使用したものを紹介します!

```kotlin:MainActivity.kt
    val linearLayout = LinearLayout(this)
    linearLayout.setPadding(0,0,0,0)        //(left:,top:,right:,bottom:)の順
    linearLayout.layoutParams.width = Int   //LinearLayoutの横幅 wrap_contentの場合要素を詰め込んでから参照すること。
    linearLayout.setBackgroundResource(R.drawable.~)    //枠線や背景をDrawableから選ぶ
```
これでLayout系を使用したデザインが簡単にできます。
他にもコードで設定できますので何かあればGoogle先生に聞いちゃいましょう！
xmlのほうが楽な場合はxmlを使用したほうがわかりやすいかもですね！

## -動的レイアウトの作成例
`For文`を使用してレイアウトを作成していきます。

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mainActivity = findViewById<LinearLayout>(R.id.MainActivity)    //トップレベルのLinearLayoutの呼び出し
        val button = findViewById<Button>(R.id.button)                      //配置したボタンの取得
        val hoge = arrayOf("Apple","Banana","Orange","Strawberry")          //表示させたい文字列
        val WC = LinearLayout.LayoutParams.WRAP_CONTENT
        val MP = LinearLayout.LayoutParams.MATCH_PARENT

        val LP = ViewGroup.LayoutParams(MP,WC)          //LinearLayout用のLayoutParams
        val textLP = LinearLayout.LayoutParams(MP,MP)   //textView用LayoutParams

        //LinearLayoutの縦バージョン
        val LinearV = LinearLayout(this).also{
            it.orientation = LinearLayout.VERTICAL
        }
        LinearV.layoutParams = LP

        var flg = true      //ボタン用のフラグ
        
        //ボタンを押したときの処理
        button.setOnClickListener {
            if (flg) {
                var i = 0
                //hoge配列の要素数分繰り返し
                for (text in hoge) {
                    //LinearLayoutの横バージョン
                    val LinearH = LinearLayout(this)
                    LinearH.layoutParams = LP
                    
                    //hoge配列内の文字列を挿入
                    val textHoge: TextView = TextView(this).also {
                        it.text = text
                        it.textSize = 20F
                        it.setTypeface(Typeface.DEFAULT_BOLD)
                    }
                    
                    //要素のindex+1分を挿入
                    val textCount: TextView = TextView(this).also {
                        it.text = (i + 1).toString()        //数値型はtoString()で文字列にしてから代入
                        it.textSize = 20F
                        it.layoutParams = textLP
                        it.gravity = Gravity.RIGHT
                    }

                    //1つずつLinearHに追加し、最後にLinearVに追加する
                    LinearH.addView(textHoge)
                    LinearH.addView(textCount)
                    LinearV.addView(LinearH)
                    i += 1
                }
                LinearV.setPadding(30, 10, 30, 10)
                mainActivity.addView(LinearV, 0)    //index指定で追加場所の変更が可能0が一番先頭
                flg = false
            }else{
                LinearV.removeAllViews()                   //LinearVの要素をすべて削除
                mainActivity.removeViewAt(0)        //mainActivityの0番目の要素を削除する
                flg = true
            }
        }
    }

}
```
```xml:avtivity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/MainActivity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Button" />
</LinearLayout>
```

XML内で変更した点は、最初に作成される`ConstraintLayout`を`LinearLayout(vertical)`に変え、ボタンを画面の一番上の真ん中に来るように配置しました。これで下のGIFのような動きをするアプリが完成しました！動的レイアウトを使いたいときはぜひ参考にしてください！他にやり方があったらご教授願います💦
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186268/1335227d-4481-770b-a9fe-a31f5415a83b.gif">
## まとめ
>- 動的レイアウトはfor文のような繰り返し処理と非常に相性が良い
>- XMLでのデザインが苦手な方はおすすめ☻

今回はこれで終わりにします、次はGoogle Mapの使い方を載せる予定です！
それでは、じゃあの～✋