Android:複数のクリック可能なボタンを持つListView要素


182

私はしましたListView、リスト内のすべての要素がTextViewの異なる2つのボタンが含まれているところを。このようなもの:

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

このコードを使用しOnItemClickListenerて、アイテム全体のを作成できます。

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

        }

    }
});

ただし、アイテム全体をクリックできるようにするのではなく、各リスト要素の2つのボタンのみをクリックします。

だから私の質問は、これらの2つのボタンのonClickListenerを次のパラメーターでどのように実装するのですか?

  • int button (要素のどのボタンがクリックされたか)
  • int position (これは、ボタンクリックが発生したリスト内の要素です)

更新:以下の私の回答に記載されている解決策を見つけました。これで、タッチスクリーンを介してボタンをクリックまたはタップできます。ただし、トラックボールで手動で選択することはできません。それは、常に全体のリスト項目を選択し、そこから私は設定していても、ボタンを無視して、次のリスト項目に直接行く.setFocusable(true)setClickable(true)のボタンのためにgetView()

また、このコードをカスタムリストアダプターに追加しました。

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

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

これにより、リスト項目を選択できなくなります。しかし、ネストされたボタンを選択可能にするのには役立ちませんでした。

誰かアイデアはありますか?


これらはまだ必要ですか?
スチュアートアクソン2010

BaseAdapterコードを見ると、areAllItemsEnabled()とisEnabled()がtrueにハードコードされているだけで、ロジックのない単純なプレースホルダーになっていることがわかります。
Artem Russakovskii

SimpleCursorAdapterを使用する場合はどうなりますか?カスタムアダプターを拡張してsimplecursoradapterを作成する必要がありますか?
oratis 2011

回答:


150

これに対する解決策は、私が思っていたよりも実際には簡単です。あなたは単にあなたのカスタムアダプタに追加することができますgetView()メソッドに、使用しているボタンのsetOnClickListener()をです。

ボタンに関連付けられた任意のデータを用いて添加されなければならないmyButton.setTag()getView()且つonClickListener経由でアクセスすることができますview.getTag()

詳細な解決策をチュートリアルとしてブログに投稿しました。


2
修繕。レポートしてくれてありがとう:-)
znq '26

クエリからcurItem.urlをどのくらい正確に取得しましたか?具体的にしますか?
oratis

1
ありがとうznq、それは私にとって非常に役に立ちました...時間の節約になりました。
ナンダゴパルT 2012

優れた例がある11時39分で、この話を見る:youtu.be/wDBM6wVEO70?t=11m39sは その後@znqが言う何をすべきか... setTag()をするときconvertView == nullのとのonClickでのgetTag()を(行います)ボタンのonClickListener()のメソッド。ありがとうございました!
Shehaaz 2013年

12
SO自体に回答があり、他のページを示さないのは素晴らしいことです。ブログのリンクは死んでいる!
gsb

63

これは一種のアペンデージ@znqの答えです...

クリックされたアイテムの行位置を知りたい場合や、行内のどのビューがタップされたのかを知りたい場合が多くあります。これは、タブレットUIではるかに重要になります。

これは、次のカスタムアダプターで実行できます。

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);
        }
    };
}

6
または、次のようなリストビューmListView =(ListView)v.getParent()。getParent();を使用することもできます。
max4ever

1
別のクラスでアダプターを使用する場合、どのようにしてポジションを取得できますか?このようなlike_c.get(position)のようなOnClickListener内の位置を単に使用しました。アダプターのgetViewメソッドで位置をfinalにすることをお勧めします。その変更を行うと、取得する位置はlisviewのすべてのアイテムで同じになります。これを解決する方法を教えてください。
Manikandan 2012年

これは、getViewメソッドの位置パラメーターを使用すると、最後に作成されたリストの項目の位置が表示されるが、クリックした項目の位置は表示されないためです
Archie.bpgc

@Manikandan:アダプターのgetView()メソッドを使用している場合、メソッドのパラメーターで位置がすでに渡されています。その場合は、setTag()などを使用して位置情報を保存できます。
greg7gkb 2012

1
アプリでコードを使用していますが、遅延後、またはリストビューをスクロールしようとしたときにクリックイベントが呼び出されます。なぜこれが起こっているのですか?
Abdullah Umer 2014

22

今後の読者のために:

トラックボールを使用してボタンを手動で選択するには:

myListView.setItemsCanFocus(true);

また、リストアイテム全体へのフォーカスを無効にするには:

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

それは私にとってはうまくいきます、私はタッチスクリーンでボタンをクリックすることができ、またキーパッドを使用してクリックを集中させる


2
これだけが私を助けてくれました!本当にありがとうございました!
Onur 2013

ExpandableListViewについてはどうですか、私はアイテムに複数のビューを持っています。
twlkyao 2014

12

私は上記のユーザーほど多くの経験はありませんが、これと同じ問題に直面し、以下のソリューションでこれを解決しました

<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イベント

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

}

興味深い解決策
シェルピア2015年

9

おそらくあなたはそれを行う方法を見つけましたが、あなたは電話することができます

ListView.setItemsCanFocus(true)

そして今、あなたのボタンはフォーカスをキャッチします


5

最善の方法であるかどうかはわかりませんが、正常に動作し、すべてのコードが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;
}

}

3

遅いのはわかりますが、これは役立つかもしれません。これは、さまざまなクリックアクション用のカスタムアダプタクラスを作成する方法の例です

 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;
    }
}

-4

この実装のプラットフォームソリューションは、長押しすると表示されるコンテキストメニューを使用しませんか?

質問の作成者はコンテキストメニューを認識していますか?リストビューにボタンを重ねるとパフォーマンスに影響があり、UIが乱雑になり、プラットフォームに推奨されるUIデザインに違反します。

反対側; コンテキストメニュー-受動的な表現を持たないという性質上、エンドユーザーにはわかりません。行動を文書化することを検討しますか?

このガイドはあなたに良いスタートを与えるでしょう。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.