Android:如何处理按钮点击

时间:2013-02-08 23:15:28

标签: java android onclicklistener android-button

在非Java和非Android领域拥有丰富的经验,我正在学习Android。

我对不同领域有很多困惑,其中之一就是如何处理按钮点击。至少有4种方法(!!!),它们被简要列出here

为了保持一致性,我将列出它们:

  1. 在活动中拥有View.OnClickListener类的成员,并将其分配给将在onClick活动方法中处理onCreate逻辑的实例。

    < / LI>
  2. 在'onCreate'活动方法中创建'onClickListener'并使用setOnClickListener

  3. 将其指定给按钮
  4. 在活动本身中实现'onClickListener'并将'this'指定为按钮的侦听器。对于活动按钮很少的情况,应分析按钮ID以执行适当按钮的“onClick”处理程序

  5. 对实现'onClick'逻辑的活动设置公共方法,并将其分配给活动xml声明中的按钮

  6. 问题#1:

    这些是所有方法,还有其他选择吗? (我不需要任何其他的,只是好奇的)

    对我来说,最直观的方式是最新的方式:它需要输入的代码量最少且最易读(至少对我而言)。

    虽然,我没有看到这种方法被广泛使用。使用它有什么用处?

    问题#2:

    这些方法的优点/缺点是什么?请分享您的经验或良好的链接。

    欢迎任何反馈!

    P.S。我试过谷歌并找到了一些关于这个话题的东西,但我发现的唯一的事情是描述“如何”这样做,而不是为什么它好或坏。

10 个答案:

答案 0 :(得分:133)

问题1: 不幸的是,你说的最直观的是在Android中使用最少的。据我所知,您应该分离UI(XML)和计算功能(Java类文件)。它还使调试更容易。通过这种方式阅读并考虑Android imo实际上要容易得多。

问题2: 我相信主要使用的两个是#2和#3。我将使用Button clickButton作为示例。

2

采用匿名类的形式。

Button clickButton = (Button) findViewById(R.id.clickButton);
clickButton.setOnClickListener( new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                ***Do what you want with the click here***
            }
        });

这是我最喜欢的,因为它的onClick方法就在使用findViewById设置按钮变量的旁边。处理此clickButton Button View的所有内容都位于此处,看起来非常整洁。

我的同事评论的一个骗局是,想象你有很多需要onclick听众的观点。你可以看到你的onCreate的篇幅会很长。这就是他喜欢使用的原因:

3

说你有,5 clickButtons:

确保您的Activity / Fragment实现OnClickListener

// in OnCreate

Button mClickButton1 = (Button)findViewById(R.id.clickButton1);
mClickButton1.setOnClickListener(this);
Button mClickButton2 = (Button)findViewById(R.id.clickButton2);
mClickButton2.setOnClickListener(this);
Button mClickButton3 = (Button)findViewById(R.id.clickButton3);
mClickButton3.setOnClickListener(this);
Button mClickButton4 = (Button)findViewById(R.id.clickButton4);
mClickButton4.setOnClickListener(this);
Button mClickButton5 = (Button)findViewById(R.id.clickButton5);
mClickButton5.setOnClickListener(this);


// somewhere else in your code

public void onClick(View v) {
    switch (v.getId()) {
        case  R.id.clickButton1: {
            // do something for button 1 click
            break;
        }

        case R.id.clickButton2: {
            // do something for button 2 click
            break;
        }

        //.... etc
    }
}

正如我的同事所解释的那样,他的眼睛更加整洁,因为所有onClick计算都在一个地方处理,而不是拥挤onCreate方法。但我看到的缺点是:

  1. 观点自己,
  2. 和onClick方法使用的onCreate中可能位于的任何其他对象都必须成为一个字段。
  3. 如果您想了解更多信息,请与我们联系。我没有完全回答你的问题,因为这是一个很长的问题。如果我找到一些网站,我会扩展我的答案,现在我只是给一些经验。

答案 1 :(得分:10)

#1 当布局上的按钮没有生成时(但显然是静态的),我经常使用最后一个。

如果您在实践中和业务应用程序中使用它,请在此处格外注意,因为当您使用像ProGuard这样的source obfuscater时,您需要在活动中标记这些方法,以免被混淆。< / p>

要使用此方法归档某种编译时安全性,请查看Android Lintexample)。


#2 所有方法的优缺点几乎相同,应该是:

  

使用最合适或最直观的方式。

如果必须为多个按钮实例分配相同的OnClickListener,请将其保存在类范围内(#1)。如果您需要一个简单的Button监听器,请进行匿名实现:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Take action.
    }
});

我倾向于不在活动中实现OnClickListener,这有时会让人感到有些困惑(特别是当你实现多个其他事件处理程序而没有人知道this正在做什么时)

答案 2 :(得分:8)

我更喜欢选项4,但它对我来说很直观,因为我在Grails,Groovy和JavaFX中做了太多工作。视图和控制器之间的“魔术”连接是共同的。为方法命名很重要:

在视图中,将onClick方法添加到按钮或其他小部件:

    android:clickable="true"
    android:onClick="onButtonClickCancel"

然后在课堂上处理方法:

public void onButtonClickCancel(View view) {
    Toast.makeText(this, "Cancel pressed", Toast.LENGTH_LONG).show();
}

再次,明确地命名方法,无论如何应该做的事情,维护成为第二性质。

一个很大的优点是您现在可以为该方法编写单元测试。选项1可以做到这一点,但2和3更难。

答案 3 :(得分:4)

最常用的方式是匿名声明

    Button send = (Button) findViewById(R.id.buttonSend);
    send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // handle click
        }
    });

此外,您可以创建View.OnClickListener对象并稍后将其设置为按钮,但您仍需要覆盖onClick方法,例如

View.OnClickListener listener = new View.OnClickListener(){
     @Override
        public void onClick(View v) {
            // handle click
        }
}   
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(listener);

当您的活动实现OnClickListener接口时,您必须在活动级别上覆盖onClick(View v)方法。然后你可以把这个活动作为按钮的监听器,因为它已经实现了接口并覆盖了onClick()方法

public class MyActivity extends Activity implements View.OnClickListener{


    @Override
    public void onClick(View v) {
        // handle click
    }


    @Override
    public void onCreate(Bundle b) {
        Button send = (Button) findViewById(R.id.buttonSend);
        send.setOnClickListener(this);
    }

}

(imho)当多个按钮具有相同的处理程序时使用的第4种方法,您可以在活动类中声明一个方法并将此方法分配给xml布局中的多个按钮,也可以为一个按钮创建一个方法,但是这个案子我更喜欢 在活动类中声明处理程序。

答案 4 :(得分:1)

选项1和2涉及使用内部类,这将使代码变得混乱。 选项2有点乱,因为每个按钮都会有一个监听器。如果您的按钮数量很少,这没关系。 对于选项4,我认为这将更难调试,因为你将不得不返回第四个xml和java代码。 当我必须处理多个按钮点击时,我个人使用选项3。

答案 5 :(得分:1)

我的示例,在Android studio 2.1中测试

在xml布局中定义按钮

<security-constraint>
    <web-resource-collection>
        <web-resource-name>InternalUserRole</web-resource-name>
        <url-pattern>/jsp/internal/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>InternalUser</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>
<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/jsp/login/login.jsp</form-login-page>
        <form-error-page>/jsp/login/login.jsp?Retry=True</form-error-page>
    </form-login-config>
</login-config>

Java脉动检测

<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

答案 6 :(得分:1)

为了简化问题,问题2说明,您可以使用这样的lambda方法来保存可变内存并避免在视图类中上下导航

//method 1
findViewById(R.id.buttonSend).setOnClickListener(v -> {
          // handle click
});

但是如果您希望在方法中立即将点击​​事件应用于您的按钮。

您可以使用@D的问题3。 Tran回答。但是不要忘记使用View.OnClickListener实现您的视图类。

在其他方面正确使用问题#3

答案 7 :(得分:0)

问题#1 - 这是处理视图点击的唯一方法。

问题#2 -
选项#1 /选项#4 - 选项#1和选项#4之间没有太大区别。我看到的唯一区别是一个案例活动是实现OnClickListener,而在另一个案例中,有一个匿名实现。

选项#2 - 在此方法中,将生成匿名类。这个方法有点麻烦,因为如果你有多个按钮,你需要多次这样做。对于匿名类,您必须小心处理内存泄漏。

选项#3 - 尽管如此,这是一种简单的方法。通常,程序员在编写之前不会尝试使用任何方法,因此这种方法并没有被广泛使用。您会看到大多数人使用选项#4。因为它在代码方面更干净。

答案 8 :(得分:0)

第1步:创建XML文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btnClickEvent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />
</LinearLayout>

第2步:创建MainActivity:

package com.scancode.acutesoft.telephonymanagerapp;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity implements View.OnClickListener {

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

        btnClickEvent = (Button) findViewById(R.id.btnClickEvent);
        btnClickEvent.setOnClickListener(MainActivity.this);

    }

    @Override
    public void onClick(View v) {
        //Your Logic
    }
}

<强> HappyCoding!

答案 9 :(得分:0)

还有各种库形式的选项可以使这个过程对使用其他MVVM框架的人非常熟悉。

https://developer.android.com/topic/libraries/data-binding/

显示官方库的示例,允许您绑定如下按钮:

<Button
    android:text="Start second activity"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:onClick="@{() -> presenter.showList()}"
/>