前提条件
SDKバージョン: 30
Androidバージョン: 9.0
一般的なEditTextに入力された値を取得する方法
おそらく皆さんこんな感じかと思います。
var name = binding.editTextName.text.toString()
var height = binding.editTextHeight.text.toString()
var weight = binding.editTextWeight.text.toString()
私の場合はViewBindingを使用しているのでこんな感じでよく書きますが、findViewById()
やKotlin extension
を利用していたとしてもさほどやり方は変わらないかと思います。要するに、取得したいeditTextのidを一つ一つ取得して、そのeditTextに入力された文字を受け取り、String型に直すという流れですね。「Android editText 値 取得」などで検索するといくらでも出てきます。
さて、入力されるeditTextが10個になったらこの作業を10回するのでしょうか。100個になったら100回するのでしょうか。一気に取得したくないですか?
EditTextに入力された値を一回で全て取得する
まず今回実現したいことは、画面に入力された3つのeditTextを一気に取得してcsvファイルに書き込むぞ!という処理です!
画面はこんな感じです。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background_color"
tools:context=".InputDataActivity">
<LinearLayout
android:id="@+id/container_for_toolbar"
android:layout_width="match_parent"
android:layout_height="120dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"></LinearLayout>
<LinearLayout
android:id="@+id/container_for_edit_text"
android:layout_width="400dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<EditText
android:id="@+id/edit_text_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="名前"
android:inputType="textPersonName"
android:textSize="24sp" />
<EditText
android:id="@+id/edit_text_height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="身長"
android:inputType="textPersonName"
android:textSize="24sp" />
<EditText
android:id="@+id/edit_text_weight"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="体重"
android:inputType="textPersonName"
android:textSize="24sp" />
<Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:text="送信する"
android:textColor="#393e46"
android:textSize="24sp"
android:textStyle="bold"
app:backgroundTint="@color/light_green"
app:rippleColor="@color/dark_green" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
入力して、送信ボタンを押すと、入力された値が一気に取得されてCSVファイルに書き込まれます。
以下のように書くと実現できます
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// bindingの初期化とsetContentViewを行う
binding = ActivityInputDataBinding.inflate(layoutInflater)
.apply { setContentView(this.root) }
// 送信ボタンをクリック
binding.btnSend.setOnClickListener {
// 引数にeditTextを格納しているコンテナのidを入れる
val patientsDataList = getAllInputData(binding.containerForEditText)
createFile(patientsDataList)
}
}
// ===== editTextに入力された値を全て取得する =====
private fun getAllInputData(group: ViewGroup): MutableList<String> {
val count = group.childCount
var editDataList = mutableListOf<String>()
for (i in 0 until count) {
val view = group.getChildAt(i)
if (view is EditText) {
Log.d("TAG", view.text.toString())
editDataList.add(i, view.text.toString())
}
}
return editDataList
}
// ===== ファイルを作成して書き込み =====
private fun createFile(patientsDataList: MutableList<String>) {
// 出力ファイルの作成
val file = File(applicationContext.filesDir, fileName)
val fw = FileWriter(file, false)
val pw = PrintWriter(BufferedWriter(fw))
// ヘッダーの指定
pw.print("名前")
pw.print(",")
pw.print("身長")
pw.print(",")
pw.print("体重")
pw.println()
// データを書き込む
val listSize = patientsDataList.size
for (i in 0 until listSize) {
if(i == listSize-1) {
pw.print(patientsDataList[listSize - 1])
pw.println()
} else {
pw.print(patientsDataList[i])
pw.print(",")
}
}
// ファイルを閉じる
pw.close()
}
上記のように書くと、getAllInputData()
メソッドにてeditText
に入力された値が一気に取得されて、List
に入ります。List
に入ったデータはcreateFile()
メソッドに渡されて、csvファイルに書き込みが行われ、内部ストレージに保存されます。このようにしてeditTextに入力された文字を一気に取得し、メソッドに一気に渡して処理してあげることができます。
getAllInputData()
での処理ですが、これは単純にeditText
をfor文で回して一つ一つ取得しているようなイメージです。試しにLog.d("TAG", view.text.toString())
の部分にブレークポイントを貼って、LogcatでTAG
と検索し、ログを逐一確認してみましょう。入力された値が一つ一つ取得されているのが確認できます。
比較
もし今回のこの処理ですが、getAllInputData()
を作成せずに書いたらどうなるのでしょうか
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// bindingの初期化とsetContentViewを行う
binding = ActivityInputDataBinding.inflate(layoutInflater)
.apply { setContentView(this.root) }
// 送信ボタンをクリック
binding.btnSend.setOnClickListener {
// この部分が増える
var name = binding.editTextName.text.toString()
var height = binding.editTextHeight.text.toString()
var weight = binding.editTextWeight.text.toString()
val patientsDataList = mutableListOf(name, height, weight)
createFile(patientsDataList)
}
}
// ===== ファイルを作成して書き込み =====
private fun createFile(patientsDataList: MutableList<String>) {
// 出力ファイルの作成
val file = File(applicationContext.filesDir, fileName)
val fw = FileWriter(file, false)
val pw = PrintWriter(BufferedWriter(fw))
// ヘッダーの指定
pw.print("名前")
pw.print(",")
pw.print("身長")
pw.print(",")
pw.print("体重")
pw.println()
// データを書き込む
val listSize = patientsDataList.size
for (i in 0 until listSize) {
if(i == listSize-1) {
pw.print(patientsDataList[listSize - 1])
pw.println()
} else {
pw.print(patientsDataList[i])
pw.print(",")
}
}
// ファイルを閉じる
pw.close()
}
どうでしょうか。増えるのはこの4行です
// この部分が増える
var name = binding.editTextName.text.toString()
var height = binding.editTextHeight.text.toString()
var weight = binding.editTextWeight.text.toString()
val patientsDataList = mutableListOf(name, height, weight)
この4行が増えましたが、代わりにprivate fun getAllInputData(...)
の処理が消えたので一見こっちの方が処理があっさりして見えますね。でも、今回は取得するeditTextがたったの3つでしたのでスッキリ見えますがこれが100個になったらどうでしょう。100個分取得しないとダメです。
// この部分が増える
var name = binding.editTextName.text.toString()
var height = binding.editTextHeight.text.toString()
var weight = binding.editTextWeight.text.toString()
val patientsDataList = mutableListOf(name, height, weight)
つまりこのコードが100行になります。
一方getAllInputData()
を使用する場合はeditTextがいくら増えようがcontainer_for_edit_text
のコンテナにeditTextが入っている限りは一回で取得できます。つまり途中でeditTextの数を増やしてもコードを変更する必要はないのです。
追記
コメントでのご指摘を受けてeditTextに入力された値を一気に取得するコードを以下のように修正しました。
// ===== editTextに入力された値を全て取得する =====
private fun getAllInputData(group: ViewGroup): MutableList<String> {
var editDataList = mutableListOf<String>()
group.children.forEachIndexed { i, view ->
if (view is EditText) {
Log.d("TAG", view.text.toString())
editDataList.add(i, view.text.toString())
}
}
return editDataList
}