Android : 여러 개의 클릭 가능한 버튼이있는 ListView 요소


182

나는했습니다 ListView목록의 모든 요소가 텍스트 뷰와 두 개의 서로 다른 버튼을 포함하는 경우를. 이 같은:

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

        }

    }
});

그러나 전체 항목을 클릭 할 수 있기를 원하지 않지만 각 목록 요소의 두 버튼 만 있습니다.

그래서 내 질문은 다음 매개 변수를 사용 하여이 두 버튼에 대해 onClickListener를 어떻게 구현합니까?

  • int button (요소의 어떤 버튼을 클릭했는지)
  • int position (버튼 클릭이 발생한 목록의 요소)

업데이트 : 아래 답변에 설명 된대로 해결책을 찾았습니다. 이제 터치 스크린을 통해 버튼을 클릭 / 탭할 수 있습니다. 그러나 트랙볼로는 수동으로 선택할 수 없습니다. 항상 전체 목록 항목을 선택하고에서 심지어 세트 불구하고, 버튼을 무시하고 다음 목록 항목에 직접 간다 .setFocusable(true)setClickable(true)의 버튼에 getView().

또한이 코드를 사용자 정의 목록 어댑터에 추가했습니다.

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

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

이로 인해 목록 항목을 더 이상 선택할 수 없게됩니다. 그러나 중첩 된 버튼을 선택하는 데 도움이되지 않았습니다.

아이디어가 있습니까?


이것들은 여전히 ​​필요합니까?
Stuart Axon

BaseAdapter 코드를 보면 areAllItemsEnabled () 및 isEnabled ()가 true로 하드 코딩되어 로직없이 간단한 자리 표시 자임을 알 수 있습니다.
Artem Russakovskii

SimpleCursorAdapter를 사용하려면 어떻게해야합니까?
oratis

답변:


150

이것에 대한 해결책은 실제로 생각보다 쉽습니다. getView()사용중인 버튼 에 대한 사용자 정의 어댑터의 메소드에 setOnClickListener ()를 추가 할 수 있습니다 .

버튼과 관련된 모든 데이터는 첨가되어야 myButton.setTag()에서 getView()와 OnClickListener를 통해 액세스 될 수있다view.getTag()

내 블로그 에 자세한 솔루션을 자습서로 게시했습니다 .


2
결정된. 보고 해 주셔서 감사합니다 :-)
znq

쿼리에서 curItem.url을 얼마나 정확하게 얻었습니까?
oratis

1
고마워 znq, 그것은 나에게 매우 유용했습니다 ... 시간을 절약했습니다.
Nandagopal T

11시 39 분 에이 이야기를 시청하십시오 : youtu.be/wDBM6wVEO70?t=11m39s 그런 다음 convertView == null 일 때 @znq의 말 ... setTag ()를 수행하고 onClick ()에서 getTag ()를 수행하십시오. 버튼의 onClickListener ()의 메소드. 감사합니다!
Shehaaz 2016 년

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
또는이 ListView와 같은 것을 사용할 수도 있습니다. mListView = (ListView) v.getParent (). getParent ();
max4ever

1
별도의 클래스에서 어댑터를 사용하면 어떻게 위치를 얻을 수 있습니까? 나는 단순히 OnClickListener 내부의 위치를 ​​사용했습니다.이 like_c.get (position)과 같습니다. 어댑터의 getView 메소드에서 최종 위치를 지정하는 것이 좋습니다. 내가 그 위치를 변경하면 lisview의 모든 항목에 대해 동일한 위치를 얻습니다. 이 문제를 해결하는 방법을 제안 해 주시겠습니까?
Manikandan 2016 년

getView 메소드의 position 매개 변수를 사용하면 가장 최근에 생성되었지만 클릭 한 목록이 아닌 목록 항목의 위치가 표시되기 때문에
Archie.bpgc

@ Manikandan : 어댑터의 getView () 메소드를 사용하는 경우 메소드 매개 변수에서 이미 위치가 전달되었습니다. 이 경우 setTag ()와 같은 것을 사용하여 위치 정보를 저장할 수 있습니다.
greg7gkb

1
내 앱에서 코드를 사용하고 있지만 지연 후 또는 목록보기를 스크롤하려고 할 때 클릭 이벤트가 호출됩니다. 왜 이런 일이 일어나고 있습니까?
압둘라 우 메르

22

미래의 독자들을 위해 :

트랙볼을 사용하여 버튼을 수동으로 선택하려면 다음을 사용하십시오.

myListView.setItemsCanFocus(true);

그리고 전체 목록 항목에 대한 초점을 비활성화하려면 :

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

그것은 나에게 잘 작동하고 터치 스크린이있는 버튼을 클릭 할 수 있으며 키패드를 사용하여 클릭 초점을 낮출 수 있습니다


2
이것 만이 나를 도와 줬다! 정말 고마워!
Onur

ExpandableListView의 경우 항목에 여러보기가 있으며 하위 항목의보기를 클릭 가능하게하고 싶습니다.
twlkyao

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 클릭 이벤트

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

}

흥미로운 해결책
sherpya

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.