Android:具有多个可点击按钮的 ListView 元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1709166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:29:38  来源:igfitidea点击:

Android: ListView elements with multiple clickable buttons

androidlistviewbutton

提问by znq

I've a ListViewwhere every element in the list contains a TextView and two different Buttons. Something like this:

我有一个ListView列表中的每个元素都包含一个 TextView 和两个不同的按钮。像这样的东西:

ListView
--------------------
[Text]
[Button 1][Button 2]
--------------------
[Text]
[Button 1][Button 2]
--------------------
... (and so on) ...

With this code I can create an OnItemClickListenerfor the whole item:

使用此代码,我可以OnItemClickListener为整个项目创建一个:

listView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> list, View view, int position, long id) {
        Log.i(TAG, "onListItemClick: " + position);

        }

    }
});

However, I don't want the whole item to be clickable, but only the two buttons of each list element.

但是,我不希望整个项目都可以点击,而只希望每个列表元素的两个按钮都可以点击。

So my question is, how do I implement a onClickListener for these two buttons with the following parameters:

所以我的问题是,如何使用以下参数为这两个按钮实现 onClickListener :

  • int button(which button of the element has been clicked)
  • int position(which is the element in the list on which the button click happened)
  • int button(元素的哪个按钮被点击了)
  • int position(这是列表中发生按钮单击的元素)


Update:I found a solution as described in my answer below. Now I can click/tap the button via the touch screen. However, I can't manually select it with the trackball. It always selects the whole list item and from there goes directly to the next list item ignoring the buttons, even though I set .setFocusable(true)and setClickable(true)for the buttons in getView().

更新:我找到了以下答案中所述的解决方案。现在我可以通过触摸屏点击/点击按钮。但是,我无法使用轨迹球手动选择它。它总是选择整个列表项,并从那里直接进入下一个表项忽略的按钮,即使我设置.setFocusable(true)setClickable(true)在按钮getView()

I also added this code to my custom list adapter:

我还将此代码添加到我的自定义列表适配器中:

@Override
public boolean  areAllItemsEnabled() {
    return false;           
}

@Override
public boolean isEnabled(int position) {
        return false;
}

This causes that no list item is selectable at all any more. But it didn't help in making the nested buttons selectable.

这会导致不再有任何列表项可供选择。但它没有帮助使嵌套按钮可选。

Anyone an idea?

任何人的想法?

采纳答案by znq

The solution to this is actually easier than I thought. You can simply add in your custom adapter's getView()method a setOnClickListener() for the buttons you're using.

解决这个问题实际上比我想象的要容易。您可以简单地在您的自定义适配器的getView()方法中为您正在使用的按钮添加一个 setOnClickListener()。

Any data associated with the button has to be added with myButton.setTag()in the getView()and can be accessed in the onClickListener via view.getTag()

与按钮关联的任何数据都必须添加到myButton.setTag()中,getView()并且可以通过 onClickListener 访问view.getTag()

I posted a detailed solution on my blogas a tutorial.

我在我的博客上发布了一个详细的解决方案作为教程。

回答by greg7gkb

This is sort of an appendage @znq's answer...

这是一种附属@znq的回答......

There are many cases where you want to know the row position for a clicked item AND you want to know which view in the row was tapped. This is going to be a lot more important in tablet UIs.

在很多情况下,您想知道被点击项目的行位置,并且您想知道行中的哪个视图被点击。这在平板电脑用户界面中将变得更加重要。

You can do this with the following custom adapter:

您可以使用以下自定义适配器执行此操作:

private static class CustomCursorAdapter extends CursorAdapter {

    protected ListView mListView;

    protected static class RowViewHolder {
        public TextView mTitle;
        public TextView mText;
    }

    public CustomCursorAdapter(Activity activity) {
        super();
        mListView = activity.getListView();
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // do what you need to do
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = View.inflate(context, R.layout.row_layout, null);

        RowViewHolder holder = new RowViewHolder();
        holder.mTitle = (TextView) view.findViewById(R.id.Title);
        holder.mText = (TextView) view.findViewById(R.id.Text);

        holder.mTitle.setOnClickListener(mOnTitleClickListener);
        holder.mText.setOnClickListener(mOnTextClickListener);

        view.setTag(holder);

        return view;
    }

    private OnClickListener mOnTitleClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = mListView.getPositionForView((View) v.getParent());
            Log.v(TAG, "Title clicked, row %d", position);
        }
    };

    private OnClickListener mOnTextClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = mListView.getPositionForView((View) v.getParent());
            Log.v(TAG, "Text clicked, row %d", position);
        }
    };
}

回答by Fabricio PH

For future readers:

对于未来的读者:

To select manually the buttons with the trackball use:

要使用轨迹球手动选择按钮,请使用:

myListView.setItemsCanFocus(true);

And to disable the focus on the whole list items:

并禁用对整个列表项的关注:

myListView.setFocusable(false);
myListView.setFocusableInTouchMode(false);
myListView.setClickable(false);

It works fine for me, I can click on buttons with touchscreen and also alows focus an click using keypad

它对我来说很好用,我可以用触摸屏点击按钮,也可以使用键盘聚焦点击

回答by Bhavin Chauhan

I don't have much experience than above users but I faced this same issue and I Solved this with below Solution

我没有比上述用户更多的经验,但我遇到了同样的问题,我用下面的解决方案解决了这个问题

<Button
        android:id="@+id/btnRemove"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@+id/btnEdit"
        android:layout_weight="1"
        android:background="@drawable/btn"
        android:text="@string/remove" 
        android:onClick="btnRemoveClick"
        />

btnRemoveClick Click event

btnRemoveClick 单击事件

public void btnRemoveClick(View v)
{
    final int position = listviewItem.getPositionForView((View) v.getParent()); 
    listItem.remove(position);
    ItemAdapter.notifyDataSetChanged();

}

回答by Rafal

Probably you've found how to do it, but you can call

可能你已经找到了怎么做,但你可以打电话

ListView.setItemsCanFocus(true)

and now your buttons will catch focus

现在你的按钮会吸引焦点

回答by mFontolan

I am not sure about be the best way, but works fine and all code stays in your ArrayAdapter.

我不确定是不是最好的方法,但工作正常并且所有代码都保留在您的 ArrayAdapter 中。

package br.com.fontolan.pessoas.arrayadapter;

import java.util.List;

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import br.com.fontolan.pessoas.R;
import br.com.fontolan.pessoas.model.Telefone;

public class TelefoneArrayAdapter extends ArrayAdapter<Telefone> {

private TelefoneArrayAdapter telefoneArrayAdapter = null;
private Context context;
private EditText tipoEditText = null;
private EditText telefoneEditText = null;
private ImageView deleteImageView = null;

public TelefoneArrayAdapter(Context context, List<Telefone> values) {
    super(context, R.layout.telefone_form, values);
    this.telefoneArrayAdapter = this;
    this.context = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.telefone_form, parent, false);

    tipoEditText = (EditText) view.findViewById(R.id.telefone_form_tipo);
    telefoneEditText = (EditText) view.findViewById(R.id.telefone_form_telefone);
    deleteImageView = (ImageView) view.findViewById(R.id.telefone_form_delete_image);

    final int i = position;
    final Telefone telefone = this.getItem(position);
    tipoEditText.setText(telefone.getTipo());
    telefoneEditText.setText(telefone.getTelefone());

    TextWatcher tipoTextWatcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            telefoneArrayAdapter.getItem(i).setTipo(s.toString());
            telefoneArrayAdapter.getItem(i).setIsDirty(true);
        }
    };

    TextWatcher telefoneTextWatcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            telefoneArrayAdapter.getItem(i).setTelefone(s.toString());
            telefoneArrayAdapter.getItem(i).setIsDirty(true);
        }
    };

    tipoEditText.addTextChangedListener(tipoTextWatcher);
    telefoneEditText.addTextChangedListener(telefoneTextWatcher);

    deleteImageView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            telefoneArrayAdapter.remove(telefone);
        }
    });

    return view;
}

}

回答by Manohar Reddy

I Know it's late but this may help, this is an example how I write custom adapter class for different click actions

我知道已经晚了,但这可能会有所帮助,这是我如何为不同的单击操作编写自定义适配器类的示例

 public class CustomAdapter extends BaseAdapter {

    TextView title;
  Button button1,button2;

    public long getItemId(int position) {
        return position;
    }

    public int getCount() {
        return mAlBasicItemsnav.size();  // size of your list array
    }

    public Object getItem(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = getLayoutInflater().inflate(R.layout.listnavsub_layout, null, false); // use sublayout which you want to inflate in your each list item
        }

        title = (TextView) convertView.findViewById(R.id.textViewnav); // see you have to find id by using convertView.findViewById 
        title.setText(mAlBasicItemsnav.get(position));
      button1=(Button) convertView.findViewById(R.id.button1);
      button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //your click action 

           // if you have different click action at different positions then
            if(position==0)
              {
                       //click action of 1st list item on button click
        }
           if(position==1)
              {
                       //click action of 2st list item on button click
        }
    });

 // similarly for button 2

   button2=(Button) convertView.findViewById(R.id.button2);
      button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //your click action 

    });



        return convertView;
    }
}

回答by Gusdor

Isn't the platform solution for this implementation to use a context menu that shows on a long press?

此实现的平台解决方案不是使用长按时显示的上下文菜单吗?

Is the question author aware of context menus? Stacking up buttons in a listview has performance implications, will clutter your UI and violate the recommended UI design for the platform.

问题作者是否知道上下文菜单?在列表视图中堆叠按钮会影响性能,会使您的 UI 变得混乱并违反平台推荐的 UI 设计。

On the flipside; context menus - by nature of not having a passive representation - are not obvious to the end user. Consider documenting the behaviour?

另一方面; 上下文菜单——本质上没有被动表示——对最终用户来说并不明显。考虑记录行为?

This guide should give you a good start.

本指南应该为您提供一个良好的开端。

http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/

http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/