如果使用 Kotlin 编写的活动,Button 的 onClick 属性是无。

34

如果我让MainActivity.java按钮的OnClick属性具有sendMessage()方法,请按照此教程:Android - Start Another Activity

但是,如果我让MainActivity.kt按钮的OnClick属性没有任何显示,只是一个none

这是Android Studio 3的BUG还是我在Kotlin中漏掉了什么?

Java MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /** Called when the user taps the Send button */
    public void sendMessage(View view) {
        // Do something in response to button
    }

}

Kotlin主活动:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    /** Called when the user taps the Send button  */
    fun sendMessage(view: View) {
        // Do something in response to button
    }
}

OnClick属性

XML布局(Java和Kotlin项目相同)

    <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
    tools:context="ir.bigbang.vahid.myapplication.MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        tools:layout_editor_absoluteX="148dp"
        tools:layout_editor_absoluteY="81dp" />
</android.support.constraint.ConstraintLayout>

1
你能把你的布局文件以XML格式发布吗?但我不建议在布局文件中设置onClick,因为这样会将编程逻辑放在视图文件中。使用kotlin-android-extensions,你可以通过id访问视图,没有必要在布局中设置它。 - Joshua
@Joshua,布局已添加。 - Vahid
6个回答

47

看起来设计师还不支持Kotlin。以下是一些解决方案:

XML(不推荐)

在您的Button标记中添加以下行。这正是设计师将要做的。

android:onClick="sendMessage"

旧时光味道

无需添加任何东西。

val button = findViewById<Button>(R.id.Button)
button.setOnClickListener {

}

kotlin-android-extensions(建议使用)

在你的build.gradle文件中添加apply plugin: "kotlin-android-extensions"

// button is the Button id
button.setOnClickListener {

}

我在build.gradle的最底部添加了'apply plugin: "kotlin-android-extensions"'。但是,你在哪里添加“// button is the Button id button.setOnClickListener {}”这一部分呢?如果你问我,入门手册中有一个错误。 - Freek
8
好的,我已经通过XML(android:onClick="sendMessage")完成了它,这很有效。但是为什么不推荐这样做呢? - Freek
4
在我看来,XML 应该只关注视图的布局,编程逻辑应该放在代码中。当其他人阅读你的代码时,他们不会知道监听器是在 XML 中添加的。此外,当你重用 XML 时,你必须确保函数必须存在于两个活动中。在 XML 中编写监听器与其他方式相比没有任何好处,因此不建议这样做。 - Joshua
1
推荐的方法已过时。 - Liam Baron

6
你的代码会像这样:

你的代码会像这样:

button.setOnClickListener(){
            Toast.makeText(this@MainActivity, "Its toast!", Toast.LENGTH_SHORT).show();
        }

这里的import

import kotlinx.android.synthetic.main. activity_main.*

这里的“button”是在.xml文件中的Button的ID。优点是您不需要在Java类中创建Button对象。


3
这是更自然的 Kotlin 方式,而且不需要获取按钮对象,很酷。 - Vishnoo Rath
"import kotlinx.android.synthetic.main.activity_main." - 带有错误 "import kotlinx.android.synthetic.main.activity_main." - 没有错误 - Fortran

4

一旦定义了sendMessage类:

/** Called when the user taps the Send button  */
fun sendMessage(view: View) {
    setContentView(R.layout.activity_second)
    // Do something in response to button
}

并且定义了第二个活动如下:
class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
    }
}

我在 OnClick 函数中添加了 SendMessage:

enter image description here

然后它就可以正常工作了。


2
你可以在XML文件中轻松定义这个内容。但是使用android:onClick属性仍然有一定的成本。
相反,你可以考虑使用Kotlin Android Extensions和合成属性:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    button.setOnClickListener {
        // Do something in response to button
    }
}

我知道这种方法。我很好奇为什么在 Kotlin 中该属性无法访问活动方法。 - Vahid
我在想,@Vahid,你是怎么发现这个问题的。我猜测ClassPath没有正确设置。现在你也让我很好奇了。 - tynn
正如@Joshua所说,它应该与Android Studio设计师相关。 - Vahid

1

按钮 OnClick 实现在 Android 中可以通过多种方式完成。

以下是一些可能的示例:

1>使用 OnClickListener 作为接口。这里我们将主活动实现为 OnClicklistener,并重写 onClick 函数。

override fun onClick(v: View?) {
        when (v?.id){
            (R.id.btn1) -> {
                toastmsg("Button1");
            }

            R.id.btn2 -> {
                toastmsg("Button2");
            }
        }
    }

2>创建一个函数,并将OnClickListener与变量sample一起传递:

        findViewById<Button>(R.id.btn3).setOnClickListener(btnClick);

var btnClick =
        OnClickListener {
            Toast.makeText(this, "BtnClick", Toast.LENGTH_SHORT).show() ;
        }

在Oncreate()中创建OnClickListener。保留HTML,不解释。
  btn1=findViewById(R.id.btn1);
        btn1?.setOnClickListener {
            toastmsg("test button1");
        }

完整的示例代码包含了Button OnClickListener的所有可能实现:

class MainActivity : AppCompatActivity() , OnClickListener{

    lateinit var tv1:TextView;
    lateinit var tv2:TextView;
    lateinit var tv3:TextView;

    var btn1: Button? =null;
    var btn2: Button? =null;
    var btn3: Button? =null;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn1=findViewById(R.id.btn1);
        btn1?.setOnClickListener {
            toastmsg("test button1");
        }

        findViewById<Button>(R.id.btn2).setOnClickListener(this);

        findViewById<Button>(R.id.btn3).setOnClickListener(btnClick);

    }

    var btnClick =
        OnClickListener {
            Toast.makeText(this, "BtnClick", Toast.LENGTH_SHORT).show() ;
        }


    override fun onClick(v: View?) {
        when (v?.id){
            (R.id.btn1) -> {
                toastmsg("Button1");
            }

            R.id.btn2 -> {
                toastmsg("Button2");
            }
        }
    }

    private fun toastmsg(msg: String){
        Toast.makeText(this, "DaggerTest" + msg, Toast.LENGTH_SHORT).show();
    }
}

0
这是我在MainActivity.kt文件中想出的解决方案。
override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val button = findViewById<Button>(R.id.button)
    button.setOnClickListener {
        sendMessage()
    }
}

/** Called when the user taps the Send button  */
private fun sendMessage() {
    val editText = findViewById<EditText>(R.id.editText)
    val message = editText.text.toString()
    val intent = Intent(this, DisplayMessageActivity::class.java).apply 
    {
        putExtra(EXTRA_MESSAGE, message)
    }
    startActivity(intent)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接