【问题标题】:Dynamically creating Buttons and setting onClickListener动态创建 Buttons 并设置 onClickListener
【发布时间】:2011-05-23 00:14:11
【问题描述】:

我在处理 Android 上动态创建的按钮时遇到问题。我正在创建 N 个按钮,单击按钮时我必须执行相同的方法,但我必须知道单击了哪个按钮。

for (int i = 0; i < NO_BUTTONS; i++){
        Button btn = new Button(this);
        btn.setId(2000+i);

        ...

        btn.setOnClickListener((OnClickListener) this);
        buttonList.addView(btn);
        list.add(btn);

目前我正在为每个按钮添加 ID,并使用下面的方法查看单击了哪个按钮。 (线btn.setId(2000+i);btn.setOnClickListener((OnClickListener) this);)。这个方法也在activity中实现。

@Override
public void onClick(View v) {
    switch (v.getId()){
        case 2000: selectButton(0);
        break;

        ...

        case 2007: selectButton(7);
        break;
    }
 }

这对我来说看起来不太好,所以我想问有没有更好的方法来做到这一点?或者如何向 onclick 事件发送一些信息?有什么建议吗?

【问题讨论】:

    标签: android button android-widget android-layout


    【解决方案1】:

    您可以创建一个返回 onclickListener 并将按钮作为参数的方法。然后使用该方法在您拥有的第一个循环中设置 onClicklistener ..

    更新:代码可能是这样的:

    View.OnClickListener getOnClickDoSomething(final Button button)  {
        return new View.OnClickListener() {
            public void onClick(View v) {
                button.setText("text now set.. ");    
            }
        };
    }
    

    作为活动中的方法,然后像这样在循环中使用它

    button.setOnClickListener(getOnClickDoSomething(button));
    

    【讨论】:

    • 是的,如果您开发桌面应用程序,这很好。但是,我们谈论的是内存较少的移动设备。因此,不是只使用一个 OnClickListener,而是创建了 8 个。好多啊。尽管它很难看,但我更喜欢第一种方法,并尝试在循环中做出选择以使其变得更好。
    • @Omer 你确定 Android 不会在编译时自行优化吗?
    • 我建议先实现干净、可维护和可读的代码,如果发现性能问题再进行优化。不是反过来。除非你的数字非常高,否则我认为这不会很重要。即使您发现问题,您仍然可以先优化该方法..例如从缓存中返回侦听器。
    【解决方案2】:

    我有一个解决方案.. 在 onCreate 中使用此代码

    linear = (LinearLayout) findViewById(R.id.linear);
    
    LayoutParams param = new LinearLayout.LayoutParams(
    LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1.0f);
    
    Button[] btn = new Button[num_array_name.length];
    for (int i = 0; i < num_array_name.length; i++) {
        btn[i] = new Button(getApplicationContext());
        btn[i].setText(num_array_name[i].toString());
        btn[i].setTextColor(Color.parseColor("#000000"));
        btn[i].setTextSize(20);
        btn[i].setHeight(100);
        btn[i].setLayoutParams(param);
        btn[i].setPadding(15, 5, 15, 5);
        linear.addView(btn[i]);
    
        btn[i].setOnClickListener(handleOnClick(btn[i]));
    
    }
    

    在 onCreate 之后创建一个返回类型为 View.OnClickListener 的方法,像这样..

    View.OnClickListener handleOnClick(final Button button) {
        return new View.OnClickListener() {
            public void onClick(View v) {
            }
        };
    }
    

    【讨论】:

    • 我在尝试在 for 循环中动态创建按钮时遇到了麻烦,因为我在循环中声明了 onClick() 方法。这种方式对我来说非常有效,因为我看到 onClick() 必须不在循环中。
    【解决方案3】:
    Button.OnClickListener btnclick = new Button.OnClickListener(){
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
    
            Button button = (Button)v;
        Toast.makeText(getApplicationContext(), button.getText().toString(),2).show();  
        }
    
    };
    

    通过btn.setOnClickListener(btnclick);调用这个监听器

    【讨论】:

      【解决方案4】:

      不应将视图 ID 用于这些目的,因为视图 ​​ID 是在编译时根据 xml 布局文件中定义的 ID 生成的。

      只需将您自己的 ID 放在视图级别可用的 setTag() 方法中(因此按钮继承它们)。这个“标签”可以是任何能让你从其他人那里识别视图的东西。您可以使用 getTag() 检索其值。

      【讨论】:

      • 我非常喜欢这里给出的想法,但发现由于 getTag() 返回一个“对象”,即使对于由整数 (1,2,...) 组成的简单标签,像 @ 这样的构造987654321@ 似乎是必要的,并且可能需要额外的 try-catch 处理,我不知道如何以优雅的方式嵌入她。使用 setId() 作为 OP 提出的建议似乎不太干净,但相比之下要容易得多。对此有何想法?
      • 如果将标签存储为 Integer,只需将类型转换为 Integer 就足够了,您无需调用 toString 方法然后将其解析为 Integer。 (Integer) v.getTag().
      【解决方案5】:

      改为使用 setTag() 函数轻松区分。

       for(int i=0;i<4;i++) {
           Button btn = new Button(this);
           btn.setTag(i);
           btn.setOnClickListener(new View.OnclickListener() {
               @Override
               public void onClick(View v) {
                   int i=v.getTag();
                   switch(i) {
                       case 1: btn.setText(i);
                           break;
      
                       case 2: btn.setText(i);
                           break;
      
                       case 3: btn.setText(i);
                           break;
      
                       case 4: btn.setText(i);
                           break;
      
                       default: btn.setText("Others");
                   }
               }
           }
      

      【讨论】:

      • 如果你必须对案例 1 到 4 做同样的事情,为什么还要单独写呢?
      • 我给出了通用代码来使用标签来区分视图...以便在循环中提供点击侦听器...
      【解决方案6】:

      “这对我来说不好看”为什么不呢?它不起作用吗?您还可以创建一个静态成员变量来保存所有已添加按钮的列表,然后在该列表中查找单击的按钮。

      【讨论】:

      • 我认为这违反了某些原则或某些东西..我不喜欢 switch 语句..我想在添加 OnClickListener 时传递一些数据/变量,以便以后知道哪个按钮被点击了..有可能吗?
      • @Ante B.:好的,你能在 onClick 方法上做这样的事情吗:selectButton(v.getId()-2000);
      • 或者,您也可以创建一个名为 SelectedBtn 的静态变量,然后在 onClick 方法上执行以下操作: SelectedBtn = v;通过这种方式,您可以引用在应用程序的其他部分中单击的那个按钮 - 请注意,这样做甚至可以避免给您的按钮提供嵌套 ID。但我完全不知道你想要做什么,所以我只是在这里拍摄......
      【解决方案7】:

      我不知道您为什么要创建 N 个按钮,看起来您的 N 值至少大于 10,如果您不想一次全部显示它们(我的意思是让它们都适合一个单一的屏幕,没有滚动)你可以尝试回收不可见的按钮,就像我们使用列表视图持有者对列表视图所做的那样。这将减少您的内存占用并提高性能,并根据您在按钮上设置的文本或标签来区分按钮,或者您甚至可以保留对这些少量按钮的引用。

      【讨论】:

      • N 的值为 [4,16],我试图立即显示它们.. 我用它们来演示排序算法..
      【解决方案8】:

      最好不要弄乱 id,setTag 和 getTag 方法就是为此目的而设计的,这是在动态布局上设置一堆按钮侦听器的快速而干净的方法

      这个答案可以帮助你: https://stackoverflow.com/a/5291891/2804001

      【讨论】:

        【解决方案9】:
        public class MainActivity extends Activity implements View.OnClickListener
        {
        
        LinearLayout linearLayout;
        Button [] button;
        View.OnClickListener listener;
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            linearLayout=(LinearLayout)findViewById(R.id.parent_lay);
            String[] array={"U123","U124","U125"};
            int length=array.length;
            System.out.println("11111111111111111111111111");
            button=new Button[length];
            for(int i=0;i<length;i++)
            {
                button[i]=new Button(getApplicationContext());
                button[i].setId(i);
                button[i].setText("User" + i);
                button[i].setOnClickListener(this);
                linearLayout.addView(button[i]);
            }
        }
        @Override
        public void onClick(View view)
        {
            view.getId();
            Button button=(Button)findViewById(view.getId());
            button.setText("Changed");
        }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-04-03
          • 2013-07-27
          • 1970-01-01
          • 2013-03-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-07
          • 1970-01-01
          相关资源
          最近更新 更多