在 kotlin 中单击按钮时如何将健康水平降低 1?

How to reduce a healthlevel by 1 when a button is clicked in kotlin?

我从科特林开始。我无法理解 OnClickListener。这里将初始健康等级设置为10后,我需要将健康等级降低1并显示出来。到目前为止,我已经初始化了 healthlevel 并设置了 onclick,但是如何声明将其减少 1 的函数并在单击按钮时调用它?

val TAG = "MyMessage"

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    Log.i("LIFECYCLE", "OnCreate")
}

private var healthLevel: Int = 10 //Set the initial health level to 10
private lateinit var healthLevelTextView: TextView
private lateinit var sneezeBtn: Button
private lateinit var takeMedicationButton: Button
private lateinit var blowNoseButton: Button

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putInt("Answer", healthLevel)
    Log.i(TAG, "Called SaveInstanceState()")
}

sneezeBtn.setOnClickListener{ _ ->
    // the function goes here 
}

您可以使用以下方式更改 healthLevel 变量:

sneezeBtn.setOnClickListener {
    healthLevel--
    healthLevelTextView.setText(healthLevel.toString())
}

附带说明一下,如果您使用 lateinit,您将失去 Kotlin 的最佳功能之一,即 Null Safety。如果你还不知道如何使用它,我建议你尽快开始学习它。

您还可以将 Android 的一个非常好的功能与 kotlin 一起使用,其中您的视图的对象会在您的 Activity 中自动生成,您只需键入 XML视图 ID,而不必在任何地方都使用 findViewById

我假设,您的代码示例在 Activity class 中并且您有一个布局文件 activity_main.xml,它看起来像这样:

    ...
        <TextView
            android:id="@+id/healthLevelTextViewId"
            ...
            />

        <Button
            android:id="@+id/sneezeBtnId"
            ...
            />
    ...

这将是具有您所需功能的代码:

class YourActivity : Activity {

    private var healthLevel: Int = 10

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // retrieve references to the text view and button
        val healthLevelTextView = findViewById<TextView>(R.id.healthLevelTextViewId)
        val sneezeBtn = findViewById<Button>(R.id.sneezeBtnId)

        // the OnClickListener must be initialized within a method body, as it is not a method itself.
        sneezeBtn.setOnClickListener { _ ->
            // implementation from the answer from Vitor Ramos
            healthLevel--
            healthLevelTextView.setText(healthLevel.toString())
        }
    }
}

您可以进一步改进代码:

  • apply plugin: 'kotlin-android-extensions' 添加到您应用的 build.gradle 文件中。然后您可以直接使用它们的 ID 引用您的视图。所以而不是
        val sneezeBtn = findViewById<Button>(R.id.sneezeBtnId)
        sneezeBtn.setOnClickListener { ... }
    
    您可以像这样直接使用 Id:
        sneezeBtnId.setOnClickListener { ... }
    
    AndroidStudio 会提示您为 sneezeBtnId.
  • 添加导入
  • 使用View Models, LiveData and Data Binding。这是推荐的,但有点更高级的技术。

Vitor 有答案,但还有几个备选方案...

您可能想要创建一个函数来更新 一起显示您的值:

fun setHealth(health: Int) {
    healthLevel = health
    healthLevelTextView.text = healthLevel
}

这将更新与显示更改结合在一起,因此这两件事总是同时发生。如果你总是用这个函数设置healthLevel(而不是直接设置变量),显示和值将始终同步

override fun onCreate(savedInstanceState: Bundle?) {
    // set your view variables, so the TextView is ready to update
    setHealth(INITIAL_HEALTH_VALUE)

如果你愿意,Kotlin lets us put a setter function on the variable itself

var healthLevel: Int = 10
    set(value) {
        field = value
        healthLevelTextView.text = health
    }

因此每次更改 healthLevel 的值时,它也会更新显示。您也可以使用 observable 委托

var healthLevel: Int by Delegates.observable(10) { _, oldValue, newValue ->
    healthLevelTextView.text = newValue
}

这些比仅仅设置值和自己更新视图更高级,只是指出它们作为替代方法存在,以及将您的逻辑保持在一个地方的方法。同样对于这些示例,它们仅 运行 您 首次设置值后的代码 - 在这两种情况下它们的默认值为 10,但初始化该默认值不会 运行 setter 代码或可观察函数。所以你仍然需要去 healthLevel = 10 让文本显示初始值。