Android:如何处理按钮点击

问题描述 投票:85回答:10

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

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

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

  1. 在活动中拥有View.OnClickListener类的成员,并将其分配给将在onClick活动方法中处理onCreate逻辑的实例。
  2. 在'onCreate'活动方法中创建'onClickListener'并使用setOnClickListener将其分配给按钮
  3. 在活动本身中实现'onClickListener'并将'this'指定为按钮的监听器。对于活动按钮很少的情况,应该分析按钮ID以执行适当按钮的'onClick'处理程序
  4. 对实现'onClick'逻辑的活动有公共方法,并将其分配给activity xml声明中的按钮

问题#1:

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

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

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

问题2:

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

欢迎任何反馈!

附:我已经尝试过谷歌并为这个主题找到了一些东西,但我发现的唯一的事情是描述“如何”这样做,而不是为什么它是好还是坏。

java android onclicklistener android-button
10个回答
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中的任何其他对象放入字段中。

如果您想了解更多信息,请与我们联系。我没有完全回答你的问题,因为这是一个很长的问题。如果我找到一些网站,我会扩展我的答案,现在我只是给一些经验。


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!


10
投票

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

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

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


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

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

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

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

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


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更难。


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布局中的多个按钮,也可以为一个按钮创建一个方法,但在这种情况下我更喜欢在活动类中声明处理程序。


1
投票

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


1
投票

我的样本,在Android studio 2.1中测试过

在xml布局中定义按钮

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

Java脉动检测

Button clickButton = (Button) findViewById(R.id.btn1);
if (clickButton != null) {
    clickButton.setOnClickListener( new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            /***Do what you want with the click here***/
        }
    });
}

1
投票

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

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

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

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

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


0
投票

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

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

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

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


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()}"
/>
© www.soinside.com 2019 - 2024. All rights reserved.