[Android] その会議いくら?を算出する
この記事を見てAndroid+Kotlin初心者の自分でも作れると思ったので作ってみました。
→ [Qiita]「その会議いくら?」を算出する(JavaScript)
環境
- 開発環境 : Android Studio 3.4.1
- 使用言語 : Kotlin 1.3.40
- 実機環境 : Zenfone 5 (ZE620KL)
出来たもの
参考にしたサイト
- [Android] ターマーやストップウォッチをSystem.currentTimeMillis() で作成するには
- 絶対UIスレッドで動作させたい処理の実装方法
- SeekBar progress 50 を Minにする方法
- int型またはlong型の文字列変換時の桁区切りについて
やった事
- ConstraintLayoutをトップとしてレイアウトを作成してみた。
- Timerを使ってタイマー処理。
- 非メインスレッドからメインスレッドUIの更新。
コード(レイアウト含む)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:text="その会議いくら?"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="32dp" android:textSize="36sp"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/linearLayout4" android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/textView" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp">
<TextView
android:text="人数 :"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/textView2"
android:gravity="center_vertical"/>
<SeekBar
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/numberOfPersonSeekBar"
android:layout_marginStart="8dp"
android:max="50"
android:layout_weight="1"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:inputType="number"
android:ems="3"
android:id="@+id/numberOfPersonEditText"
android:textSize="24sp"
android:layout_marginStart="8dp"/>
<TextView
android:text="人"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/textView7" android:textSize="24sp"
android:layout_marginStart="8dp" android:gravity="center_vertical"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_marginTop="64dp"
app:layout_constraintTop_toBottomOf="@id/linearLayout4" app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp" android:id="@+id/linearLayout">
<Button
android:text="Start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/startButton" android:layout_weight="1"/>
<Button
android:text="Stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/stopButton" android:layout_weight="1"/>
<Button
android:text="Reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/resetButton" android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_weight="1"
android:id="@+id/linearLayout3" android:layout_marginTop="64dp"
app:layout_constraintTop_toBottomOf="@+id/linearLayout" android:layout_marginStart="8dp"
app:layout_constraintStart_toStartOf="parent" android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent">
<TextView
android:text="経過時間 :"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView3" android:textSize="30sp" android:layout_weight="1"
android:gravity="center"/>
<TextView
android:text="XXX 秒"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/elapsedTimeTextView" android:textSize="60dp" android:layout_weight="1"
android:gravity="center"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp"
android:layout_marginTop="24dp" app:layout_constraintTop_toBottomOf="@+id/linearLayout3">
<TextView
android:text="コスト"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView4" android:textSize="30sp" android:layout_weight="1"
android:gravity="center"/>
<TextView
android:text="X,XXX,XXX 円"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/costTextView" android:textSize="60sp" android:layout_weight="1"
android:gravity="center"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
package jp.session.kikikiroku.howmuchisthemeeting
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.SeekBar
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
class MainActivity : AppCompatActivity() {
class CostTimerCallback(val costTimer: CostTimer) : TimerTask() {
override fun run() {
costTimer.update(1)
}
}
class CostTimer(val activity: MainActivity) {
private var timerInstance: Timer? = null
private var usingSec: Long = 0
fun start() {
stop()
timerInstance = Timer()
timerInstance?.schedule(CostTimerCallback(this), 1000, 1000)
}
fun stop() {
if(timerInstance != null) {
timerInstance?.cancel()
timerInstance = null
}
update(0)
}
fun reset() {
usingSec = 0
update(0)
}
fun update(addSec: Long) {
usingSec += addSec
// time
activity.setElapsedTime(usingSec.toInt())
// cost
val averageMonthlyCost = 400000.0 // 40万/月
val averageMonthlyWork = 160.0 // 160時間/月
var costPerSecond = averageMonthlyWork * 3600 / averageMonthlyCost
var person = Integer.parseInt(activity.numberOfPersonEditText.text.toString())
var cost = (costPerSecond * usingSec * person).toInt()
activity.setCost(cost)
}
}
private val costTimer: CostTimer = CostTimer(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
numberOfPersonSeekBar.progress = 5
// numberOfPersonSeekBar.min = 1
numberOfPersonSeekBar.max = 20
numberOfPersonSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
// ツマミをドラッグしたときに呼ばれる
numberOfPersonEditText.setText(progress.toString())
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
// ツマミに触れたときに呼ばれる
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
// ツマミを離したときに呼ばれる
}
} )
numberOfPersonEditText.setText(numberOfPersonSeekBar.progress.toString())
startButton.setOnClickListener{onClickStartButton()}
stopButton.setOnClickListener{onClickStopButton()}
resetButton.setOnClickListener{onClickResetButton()}
setElapsedTime(0)
setCost(0)
}
private fun setElapsedTime(timeSec: Int) {
elapsedTimeTextView.post{elapsedTimeTextView.text = "%,d".format(timeSec.toLong()) + " 秒"}
}
private fun setCost(costYen: Int) {
costTextView.post{costTextView.text = "%,d".format(costYen.toLong()) + " 円"}
}
private fun onClickStartButton() {
costTimer.start()
}
private fun onClickStopButton() {
costTimer.stop()
}
private fun onClickResetButton() {
costTimer.reset()
}
}
まとめ
- Androidのタイマーは別スレッドなのでUI操作は注意する。
- シークバーの最小値設定はAPI Level 26から。