목록의 버튼을 사용하여 Listactivity에서 onListItemClick을 실행하는 방법은 무엇입니까?


89

사용자 지정 ListAdapter를 사용하여 목록에서보기를 생성하는 간단한 ListActivity가 있습니다. 일반적으로 ListAdapter는 뷰를 TextViews로 채울 것이지만 이제는 버튼도 여기에 넣고 싶습니다.

그러나 목록 항목에 포커스 가능한 뷰를두면 목록 항목을 클릭 할 때 ListActivity에서 onListItemClick ()이 실행되는 것을 방지하는 것은 내 이해와 경험입니다. 버튼은 여전히 ​​목록 항목 내에서 정상적으로 작동하지만 버튼 이외의 항목을 누르면 onListItemClick이 트리거되기를 원합니다.

이 작업을 어떻게 할 수 있습니까?


5
Focusability 후손이있는 솔루션이 정말 도움이됩니다. 답변으로 추가하고 수락해야합니다!
Maksym Gontar

@Max 내가하지 않는 이유는 그것이 정말 나쁜 습관이기 때문입니다. 영구적 인 건강한 해결책을 찾았다면 대답 할 것입니다 (내가 1 년 전에이 질문을 썼다는 것을 기억한다면 :))
CodeFusionMobile

또한 해결 방법을보고 싶습니다. 하위 포커스를 설정하려고했지만 버튼으로 작동하지 않습니다. 또한 목록 행에 GridView (ImageViews 포함)를 넣으려고했는데 비슷한 문제가 있습니다.
MrPurpleStreak

내가 준 IMHO 대답은 Ramps와 Praveen이 제안한 것보다 문제에 대한 훨씬 더 우아한 해결책입니다. PsNot 여기 잊혀진 질문을 부활하려고하지만 난 u는 아직 대답을 수락하지 않았습니다 참조; D
Ewoks

@CodeFusionMobile Ewoks의 답변을 받아 주시겠습니까? 가장 많이 득표 한 답변은 ListView 요소 (파란색으로 바뀜)에 대한 onclick 애니메이션을 비활성화하기 때문에 결함이 있습니다. 다른 개발자가 최고 답변을 시도하고 결함이 있음을 확인한 다음 Ewoks로 이동하는 데 소요되는 시간을 절약 할 수 있습니다.
1 ''

답변:


99

이전 주석 솔루션 에서 썼 듯이 ImageButton에서 setFocusable (false)입니다.

목록 요소의 android:descendantFocusability="blocksDescendants" 루트 레이아웃 에 추가하려는 더 우아한 솔루션이 있습니다 . 그러면 ListItem에 대한 클릭이 가능하고 별도로 Button 또는 ImageButton 클릭을 처리 할 수 ​​있습니다.

도움이되기를 바랍니다;)

건배


3
android:descendantFocusability="blocksDescendants"완벽했습니다.
Matthew Mitchell

1
당신, 나의 친구는 나의 개인적인 영웅입니다. 당신은 최고의 투표를 받아야합니다! 이것은 거의 모든 경우에 훨씬 좋습니다!
OschtärEi

이것은 받아 들여진 대답이어야합니다. 그것은 나를 위해 완벽하게 작동했습니다. 목록 항목의 모든보기가 초점을 맞출 필요가없는 것처럼 보이며 개별적으로 설정하지 않고 바로 수행합니다.
rushinge 2013 년

1
이것은 나를 위해 작동하지 않는 것 같습니다. 루트 레이아웃이란 행 레이아웃 또는 목록보기가 정의 된 위치를 의미합니까? 어쨌든, 가능한 모든 조합을 시도했습니다. 작동하지 않습니다. :(
GreenBee

내가 쓴 것처럼 "목록 요소의 루트 레이아웃".. 그래서 당신이 여러 개의 Button, ImageButton, TextVeiw를 가진 레이아웃 (목록 요소의 루트 레이아웃이라고 부름)으로 구성된 목록을 가지고 있다고 가정 해 봅시다.
Ewoks

59

여기서 도와 드릴 수 있기를 바랍니다. listView 항목에 대한 사용자 지정 레이아웃이 있다고 가정하고이 레이아웃은 버튼과 TextView, ImageView 등과 같은 다른보기로 구성됩니다. 이제 버튼 클릭시 다른 이벤트가 발생하고 클릭 된 다른 모든 이벤트에서 다른 이벤트가 발생하기를 원합니다.

ListActivity의 onListItemClick ()을 사용하지 않고도이를 달성 할 수 있습니다.
수행해야 할 작업은 다음과 같습니다.

사용자 지정 레이아웃을 사용하고 있으므로 사용자 지정 어댑터에서 getView () 메서드를 재정의하고있을 수 있습니다. 트릭은 버튼에 대해 다른 리스너를 설정하고 전체 뷰 (행)에 대해 다르게 설정하는 것입니다. 예를 살펴보십시오.

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            List<String> objects) {
        super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String text = getItem(position);
        if (null == convertView) {
            convertView = mInflater.inflate(R.layout.custom_row, null);
        }
        //take the Button and set listener. It will be invoked when you click the button.
        Button btn = (Button) convertView.findViewById(R.id.button);
        btn.setOnClickListener(this);
        //set the text... not important     
        TextView tv = (TextView) convertView.findViewById(R.id.text);
        tv.setText(text);
        //!!! and this is the most important part: you are settin listener for the whole row
        convertView.setOnClickListener(new OnItemClickListener(position));
        return convertView;
    }

    @Override
    public void onClick(View v) {
        Log.v(TAG, "Row button clicked");
    }
}

OnItemClickListener 클래스는 다음과 같이 선언 할 수 있습니다.

private class OnItemClickListener implements OnClickListener{       
    private int mPosition;
    OnItemClickListener(int position){
        mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
        Log.v(TAG, "onItemClick at position" + mPosition);          
    }       
}

물론 OnItemClickListener 생성자에 더 많은 매개 변수를 추가 할 것입니다.
그리고 한 가지 중요한 것은 위에 표시된 getView의 구현이 매우 추악합니다. 일반적으로 findViewById 호출을 피하기 위해 ViewHolder 패턴을 사용해야하지만 이미 알고있을 것입니다.
내 custom_row.xml 파일은 ID "button"의 Button, ID "text"의 TextView 및 ID "image"의 ImageView가있는 RelativeLayout입니다.
문안 인사!


9
내 솔루션은 결국 다른 방식으로 진행되었습니다. 목록 행 레이아웃의 자손 Focusability 속성을 하위 항목을 차단하도록 설정하여 문제를 해결했는데 갑자기 작동했습니다. 이제 사용자 지정 뷰 바인더가 연결된 simpleCursorAdapter를 사용하여 이벤트 설정 및 버튼과 관련된 기타 멋진 작업을 수행합니다.
CodeFusionMobile 2010 년

3
이 솔루션을 사용했습니다. 그러나 경고 : onClick 핸들러로 인해 목록의 내용이 변경되어 getView가 호출되고 위젯이 ToggleButton 또는 CheckBox와 같은 상태 저장 상태이고 getView가 해당 상태를 설정하는 경우 setOnClickListener를 사용할 수 있습니다. (null) 루프 효과를 피하기 위해 onView에서 상태를 변경하기 전에.
Pierre-Luc Paour 2011 년

3
내 솔루션은 어떻습니까? 우리가 필요할 때마다 좀 더 우아하고 쉽게 적용 할 수있는 인상을 ..
Ewoks

첫 번째 의견은 답으로 인정해야한다, 그래서 나 같은 사람들은 그것을 찾기 위해 시간이 필요하지 않을
keybee을

감사! 이것은 유용했습니다. 다른 스레드에서 설명한 focus : blockDescendants 접근 방식에 대한보다 지역화 된 대안으로 선호합니다.
Yoav Shapira 2013

18

사용자 지정 ListView에 포커스 가능한 요소가 포함되어 있으면 onListItemClick이 작동하지 않습니다 (예상되는 동작이라고 생각합니다). 사용자 정의보기에서 초점을 제거하면 트릭이 수행됩니다.

예를 들면 :

public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
         super(context);
         …
         mText.setFocusable(false);
         mText.setFocusableInTouchMode(false);

         mCheckBox.setFocusable(false);
         mCheckBox.setFocusableInTouchMode(false);
        …       
    }
}

3
나는 당신의 솔루션이 마음에 듭니다. 행당 "클릭 가능한"위젯이 하나만있는 경우 포커스 가능성을 거부하는 것은 우아한 솔루션입니다. 행의 아무 곳이나 탭하면 일치하지만 위젯이 라디오 또는 확인란 일 때 유용한 동작입니다. android : focusable = "false"및 android : focusableInTouchMode = "false"를 사용하여 XML에서 동일한 결과를 얻을 수 있습니다.
Pierre-Luc Paour 2011 년

1
당신은 가시성을 변경하는 경우 하나의 표시로 "보기"를 설정 한 후 코드를 통해 그것을 할 수있다 있도록 XML의 방법은 작동하지 않는 것
max4ever

13

나는 같은 문제가 있습니다 : OnListItemClick not fired! [해결됨]
ListActivity를 확장하는 클래스에서 발생
합니다. TextBox 및 ListView를 포함하는 ListActivity의 레이아웃이 LinearLayout에 중첩되고
행에 대한 다른 레이아웃 (LineraLayout에 중첩 된 CheckBox 및 TextBox)이 있습니다.

그게 코드입니다.

res / layout / configpage.xml (ListActivity의 기본)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" > 
    <TextView  
        android:id="@+id/selection"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="pippo" /> 
    <ListView  
        android:id="@android:id/list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:drawSelectorOnTop="false"  
        android:background="#aaFFaa" > 
    </ListView> 
<LinearLayout> 

res/layout/row.xml (layout for single row)  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content"> 
  <CheckBox  
      android:id="@+id/img"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 

  <TextView  
      android:id="@+id/testo"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 
</LinearLayout> 

src /.../.../ ConfigPage.java

public class ConfigPage extends ListActivity
{
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.configpage);  
        // loaded from res/value/strings  
        String[] azioni = getResources().getStringArray(R.array.ACTIONS);  
        setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row, 
                R.id.testo,   azioni));  
        selection = (TextView) findViewById(R.id.selection);  
    }       

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
        selection.setText(" " + position);
    }
}

row.xml에 추가하면 작동하기 시작합니다.

  • android:focusable="false"
  • android:focusableInTouchMode="false"

Eclipse 3.5.2
Android SDK 10.0.1
min SDK 버전을 사용합니다. 3

나는 이것이 도움이되기를 바랍니다
... 그리고 내 영어에 대해 죄송합니다 :(


@fellons는 이유를 모르지만 나를 위해 작동하지 않았습니다. 내 onListItemClick이 호출되지 않습니다.
likejudo

속성 코드 android : focusable = "false"및 android : focusableInTouchMode = "false"코드를 추가 했습니까?
rfellons

2

android:focusable="false"버튼의 속성 중 하나로 추가 하세요.


1

ToggleButton에서 동일한 문제가 발생했습니다. 반나절 동안 벽에 머리를 부딪친 후 마침내 문제를 해결했습니다. 'android : focusable'을 사용하여 포커스 가능한 뷰를 포커스 불가능하게 만드는 것만 큼 간단합니다. 또한 목록 행의 초점 및 클릭 가능성 (단어를 구성했습니다)을 사용하지 말고 기본값으로 두십시오.

물론 이제 목록 행의 포커스 가능한 뷰가 포커스를받을 수 없으므로 키보드를 사용하는 사용자는 포커스를 맞추는 데 문제가있을 수 있습니다. 문제가되지 않을 것 같지만 100 % 완벽한 앱을 작성하려는 경우 onItemSelected 이벤트를 사용하여 선택한 행의 요소에 초점을 맞추고 이전에 선택한 행의 요소에 초점을 맞출 수 없게 만들 수 있습니다.


이 접근 방식을 사용했습니다. 개별 항목에 집중할 수없는 문제를 해결할 수 있다면 가장 간단한 방법입니다. 이것은 또한 목록 항목에 대한 상태 드로어 블을 그대로 유지하며 다른 해결 방법 중 일부는 그렇지 않습니다.
Jonathan S.

1
 ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
  // When clicked, show a toast with the TextView text
  Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
      Toast.LENGTH_SHORT).show();
}
});

-1

항목 내에 내 값을 보유하는 개체를 인스턴스화하는 getListAdapter (). getItem (position)을 사용했습니다.

MyPojo myPojo = getListAdapter().getItem(position);

그런 다음 myPojo에서 getter 메서드를 사용하여 항목 내에서 적절한 값을 호출합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.