アンケート画面などで複数のTextViewやCheckBoxが繰り返し表示される画面を作成するときレイアウトファイル(.xml)が冗長的になってしまうことがあるかと思います。
以下の画像のようなチェックボックスが複数個並んだViewを作成するとします。

この時のレイアウトファイルとして真っ先に考えられるのはこんな感じかなっと思います。
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<CheckBox
android:id="@+id/checkBox1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="チェック項目1" />
<CheckBox
android:id="@+id/checkBox2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="チェック項目2" />
<CheckBox
android:id="@+id/checkBox3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="チェック項目3" />
<CheckBox
android:id="@+id/checkBox4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="チェック項目4" />
<CheckBox
android:id="@+id/checkBox5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="チェック項目5" />
<CheckBox
android:id="@+id/checkBox6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="チェック項目6" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
この記事ではこのような冗長的なレイアウトファイル(CheckBoxが描画したい数だけレイアウトファイルに繰り返されている)から脱却する実装方法を紹介します。
例でチェックボックスを扱っていますがTextViewやImageViewでも同様に実装できます。
描画するCheckboxのenum classを作成
最初に描画するチェックボックスをそれぞれenum
で定義します。
// isCheckはデフォルトでチェックをつけるかのフラグ
enum class CheckboxList(@StringRes val title: Int, val isCheck: Boolean) {
FIRST(R.string.checkbox1, true),
SECOND(R.string.checkbox2, false),
THIRD(R.string.checkbox3, false),
FORTH(R.string.checkbox4, false),
FIFTH(R.string.checkbox5, true);
}
.ktファイルで実装する
CheckBoxやTextViewなどはActivityやFragmentの中でも生成することができるので、そちらを利用します。
※DataBindingを使用します。
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
createCheckBox()
}
private fun createCheckBox() {
/**
* CheckboxListに定義されている要素の数だけ繰り返す。
*/
CheckboxList.values().forEachIndexed { index, checkboxList ->
val checkbox = Checkbox(requireContext()) // Checkboxインスタンスの生成
checkbox.apply {
id = index // チェックボックスのリソースIDを設定(今回は0~4)
text = requireContext().resources.getText(checkboxList.title) // enumに定義されたタイトルをセット
isCheck = checkboxList.isCheck
}
binding.linearView.addView(checkbox) // linearView(LinearLayout)にcheckboxを追加
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
<LinearLayout
android:id="@+id/linear_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
このようにコードベースで実装することで冗長的なレイアウトファイルから脱却できます。
また、チェックボックスが追加になった場合でもenum
に要素を追加すればいいため修正コストも下がると思います。
今回はチェックボックスで実装しましたが、TextViewやButton、ImageViewでもできると思うので冗長的なレイアウトになりそうな時はこちらの手法も考えて見てはいかがでしょうか?