在Android中定义按钮事件的最佳做法


67

我有一个LayoutXML定义,其中包含几个Button

当前,我正在通过OnCreate方法来针对按钮定义事件处理程序:

public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button newPicButton = (Button)findViewById(R.id.new_button);
    newPicButton.setOnClickListener(btnListener);
    ..... similarly for other buttons too
    .....
}

ButtononClick事件内部,我启动相机Intent以获取图片,并在onActivityResult回调内部,再次设置事件处理程序并设置View如下:

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{ 
    setContentView(R.layout.main);
    Button newPicButton = (Button)findViewById(R.id.new_button);
    newPicButton.setOnClickListener(btnListener);
    ...similarly for other buttons too
}

我是android的新手,每次重新定义事件的方法对我来说似乎很肮脏。我想知道在这种情况下定义按钮事件处理程序的最佳实践是什么。

编辑:粘贴我的完整课程

public class CameraAppActivity extends Activity 
{
    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button newPicButton = (Button)findViewById(R.id.new_button);
        newPicButton.setOnClickListener(btnListener);
    }

    //---create an anonymous class to act as a button click listener---
    private OnClickListener btnListener = new OnClickListener()
    {

        public void onClick(View v)
        {   
             //Intent newPicIntent = new Intent(v.getContext(), NewPictureActivity.class);
             //startActivityForResult(newPicIntent, 0);
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(cameraIntent, 999);
        } 

    };  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {  

        setContentView(R.layout.main);
        Button newPicButton = (Button)findViewById(R.id.new_button);
        newPicButton.setOnClickListener(btnListener);

       //if I comment last two lines nothing happens when I click on button

    }  

主要的问题是

setContentView(R.layout.main);
Button newPicButton = (Button)findViewById(R.id.new_button);
newPicButton.setOnClickListener(btnListener);

onActivityResult..内部重新注册事件是否正确?还是我做错了什么?因为如果我不重新注册事件,那么当我单击按钮时什么也不会发生。


2
你不应该在重新设置他们onActivityResult(),如果他们在已经建立onCreate()
威尔泰特

:S如果我在意图后不返回主视图时不执行此操作,则单击按钮不会发生任何事情
Haris Hasan

Answers:


64

为什么不在XML布局中注册onClick事件,然后在代码中处理它。这就是我要做的:

<Button
android:id="@+id/my_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"
android:onClick="onBtnClicked">
</Button>

现在创建一个可以处理点击的方法

public void onBtnClicked(View v){
    if(v.getId() == R.id.my_btn){
        //handle the click here
    }
}

或者,您可以为代码中的每个项目分别设置OnClickListener。然后使用if / else或switch语句确定起点。

这样,您可以使用一种方法来处理一种布局中的所有按钮。

更新:
尽管这是一种有效的方法,但我强烈建议您使用第二种方法。它更清洁,更易于维护,尤其是在处理碎片时。


10
使用片段时,在布局中包含“ onClick”效果不佳。请看一看这个SO后:stackoverflow.com/questions/6091194/...
扎卡里亚

4
这也使您的代码难以更改。重命名xml中的内容不会影响代码。
DArkO

4
一旦开始使用Fragments,几乎就不可能维护它。更好的方法是让您的片段类实现OnClickListener接口。
凯尔·法尔康纳

1
非常糟糕的做法,使代码很难维护。
本杰明·

1
当您的应用开始变得越来越大时,这会给***带来痛苦。一种更干净和可维护的方法是在Java代码中定义侦听器。
Axxiss

39

这是使用代码的最佳方法:

  public class MyTest extends Activity implements OnClickListener{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     //... some other code here to init the layout
        Button btn1 = (Button)findViewById(R.id.button1);
        Button btn2 = (Button)findViewById(R.id.button2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch(v.getId()){
            case R.id.button1:
                break;
            case R.id.button2:
                break;
        }
    }
}

带接口的新类仅在您希望实现分离时才有用(当您想在其他地方使用相同的类代码,然后将其移至另一个单独的类文件等)。当前正在进行的活动以及onClick的实现取决于它在运行时是否引用了定义的对象,您肯定应该使用我建议的方法。

仅当您想要在单独的类或活动之间实现交流并使事情分开时,创建类接口才是好选择。除此之外,为此创建子类是一种不好的做法。


11

这是最好的方法

@Override
public void onCreate(Bundle savedInstanceState) {
        button1.setOnClickListener(onClickListener);
        button2.setOnClickListener(onClickListener);
        button3.setOnClickListener(onClickListener);
}

private OnClickListener onClickListener = new OnClickListener() {
     @Override
     public void onClick(final View v) {
         switch(v.getId()){
             case R.id.button1:
                  //DO something
             break;
             case R.id.button2:
                  //DO something
             break;
             case R.id.button3:
                  //DO something
             break;
         }

   }
};

8

没有定义最佳实践。这在很大程度上取决于用例。您可以使用Button的onClick属性在XML布局中定义它们。

XML范例:

<!-- Stuff -->
<Button android:id="@+id/my_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Click Me!"
    android:onClick="myClickMethod" />

Java示例:

// stuff
public void myClickMethod(View v) {
    // more stuff
}

这样,您就不必OnClickListener自己实施。您可以为每个Button分配相同的onClick方法,然后根据每个视图简单地决定要触发的操作,也可以为每个Button拥有单独的方法。

通常,我建议不要将OnClickListener一个按钮用于多个按钮。如果您使用描述性名称(无论如何应该这样做),则更容易理解每​​个侦听器应该做什么。


2
v.getId() is not same as 可行,但是不知道为什么R.id.takepic_button` takepic_button是我用来设置XML事件的按钮
Haris Hasan11年

我不知道 那是你必须要发现自己的东西。
Octavian A. Damiean 2011年

抱歉,我的错误确实很不错,这正是我想要的
Haris Hasan

8

我喜欢使用黄油刀的“现代” DI方法:

  1. 声明你的看法
@InjectView(R.id.buttonAlert) 
Button buttonAlert;
  1. 注入所有带注释的资源
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.inject(this);
 }
  1. 注释并实现您的onClick方法
@OnClick(R.id.buttonAlert)
public void alertClicked(View v){
    // your logic
}

2

@Hasan这是我发现的最佳方法,并且每次都能完美地为我工作。

  • 在Layout.xml中,定义按钮的onClick

                    <Button android:id="@+id/Button01"          
                        android:onClick="@string/method" 
                        android:focusable="true" android:clickable="true"
                        ">
                    </Button>
    
  • 在R.string文件中添加以下行

字符串名称=“方法”> buttonFunction

  • 在sample.java文件中,单击按钮将调用R.string中定义的函数,其外观应类似于

    public void buttonFunction(View view){//像单击按钮一样对您进行编码}


0

您的Activity应该实现OnClickListener,并且应该在单个OnCLick()方法中为所有按钮编写所有事件处理。


0

问题是按钮newPicButton的对象被创建为本地对象,该对象仅在onCreate函数的范围内有效,并且一旦代码退出该函数,垃圾回收器就会为该按钮取消分配对象。您需要做的是在任何方法外部声明newPicButton对象,然后在onCreate方法中为其分配一个侦听器。这将解决您的问题,我希望我已经解释了为什么在onActivityResult方法中删除newPicButton的代码时什么也没发生的原因:)


那正是我的想法和所做的,但即使如此,也没有任何反应
Haris Hasan

0

我知道这很旧,但是如果有人想知道为什么不能onClickListener从添加onActivityResult,那是因为按钮为空。如果您再次初始化它(就像在中一样onCreate),则可以添加侦听器。不过请注意,其他所有内容也都将为null,因此EditText,例如,如果要从中获取数据,则也必须对其进行初始化(简单检查一下lisneter中的对象是否为null即可)。 。


-1

这是我的做法:

  1. 在Buttons XML文件中设置android:onClick =“ onClick”。
  2. 在您的活动中实现View.OnClickListener。
  3. 在onClick方法中,使用Switch键(如下所示)。

@Override

public void onClick(View view) {
    Intent intent;
    switch(view.getId()){

        case R.id.home_button:
            //DO something
            intent = new Intent(HashTagActivity.this,MainActivity.class);
            startActivity(intent);
            break;
        case R.id.back_button:
            //DO something
             intent = new Intent(HashTagActivity.this,ClassActivity.class);
            startActivity(intent);
            break;
        case R.id.favorite_button:
            //DO something
            break;
        case R.id.copy_button:
            //DO something

            break;

    }
}

效果很好。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.