2014-12-06 13 views
4

ListView를 클릭하여 배경을 변경하려고합니다. 그러나 그것은 실제로 가능하지 않습니다. 그 일을하는 예제가있는 게시물이 많이 있지만 신뢰할 수있는 것은 없습니다. 내가 이해 한대로 - 그것은 어떻게 든 "재활용"과 관련이 있습니다.ListView에서 setSelected() 버그가 발생했습니다.

어댑터의 OnItemClickListener에서 view.setSelected()를 호출하고 내 설정에 따라 선택한 항목에 다른 배경을 잘 적용합니다. 그러나 ListView가 공간 부족 (정확히는 중요하지 않음)과 Scollbar가 ListView 내부에 나타나거나 사라지는 항목을 선택하면 안드로이드가 내 선택을 잊어 버리고 기본 스타일이 적용됩니다. 화면을 회전 할 때와 동일한 버그가 발생합니다. 항목이 선택 해제됩니다. 그래서 나는 어댑터의 getView()가 호출되는 동안 "deselection"이 발생한다고 생각한다.

내 onClick 이벤트가 json 요청을 백그라운드 서비스에 보내고 json 응답을 수신하고 디코딩하는 것을 유발하므로 항목 클릭과 활동 내용 변경 사이에 시간이 걸립니다. 이것은 다음과 같습니다.

  1. ListView 항목을 클릭합니다. 배경을 "선택한 색상"으로 변경합니다.
  2. 몇 분 전 기다리고 있습니다.
  3. 활동 내용은 서비스 응답에 따라 변경됩니다. ListView 안에 스크롤 막대가 나타납니다. 항목 배경이 "기본 색상"으로 변경됩니다 (항목 선택 취소됨).

스크롤바가 나타나지 않는 항목을 클릭하면 서비스 응답 처리 후 선택된 항목의 선택이 해제되지 않습니다.

어댑터의 getView() 내에서 setSelected()를 호출하면 버그에 아무런 영향을 미치지 않습니다. 항목이 아직 선택 해제 중입니다. getView()에서 항목의 배경을 수동으로 설정하려고 시도했다. 스크롤바의 모양을 일으키는 항목이 제대로 작동하기 시작했지만 스크롤바의 모양이 나타나지 않는 항목이 더 재미있어졌다. getView() 호출) 작동이 중지되었습니다!

모든 코드는 매우 복잡하므로 몇 가지 중요한 단편을 게시 할 것입니다. 여기 내 OnItemClickListener입니다 :

private AdapterView.OnItemClickListener onCategoryClickListener = 
     new AdapterView.OnItemClickListener() { 
    @Override 
    public void onItemClick(AdapterView<?> parent, final View view, final int position, 
      long id) { 
     categoriesAdapter.setSelectedPosition(position); 
     view.setSelected(true); 
     // More code here 
    } 
}; 

여기 내 어댑터의 코드 조각입니다 :

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item 
     android:drawable="@color/list_item_default_color" 
     android:state_selected="false" /> 
    <item 
     android:drawable="@color/list_item_selected_color" 
     android:state_selected="true"/> 
</selector> 

내가 그것을 작동하게하는 방법은 많이 검색 : 여기

private int selectedPosition; 
private boolean selectable = true; 

public void setSelectedPosition(int position) { 
    this.selectedPosition = position; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    TextView label = (TextView) View.inflate(context, textViewResourceId, null); 
    label.setText(getName(values.get(position))); 
    if(selectable) { 
     label.setBackgroundResource(R.drawable.list_selector); 
     if(position == selectedPosition) { 
      label.setSelected(true); // This does not work. Why? 
      label.setBackgroundColor( // This gives strange results 
       context.getResources().getColor(R.color.list_item_selected_color)); 
     } else { 
      // Similar code here, but for deselecting items. 
     } 
    } 
    return label; 
} 

과 나의 선택이다 그러나 아무것도 도움이되지 않습니다. -이 방법은 무엇

  • ()는
  • 실행 list.setSelection() view.post의 내부 view.setSelected()을 실행 : 여기에 내가 시도 몇 가지입니까? 그것은 아무것도하지 않는다!
  • textView를보다 정확하게 초기화하면서 convertView가 null인지 확인하십시오. 좋지 않은 나쁜 결과를줍니다 - ListView 항목을 임의로 선택 상태로 만듭니다 (선택 상태에 아무런 영향을 미치지 않음).
  • Item에 복잡한 레이아웃이 없기 때문에 ViewHolder를 사용하지 않았습니다. 간단한 TextView 만 있습니다.

답변

10

:

<ListView 
     android:choiceMode="singleChoice" /> 

2) 당신의 선택에 당신의 품목 레이아웃의 루트 요소의 배경을 설정합니다 :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:background="@drawable/selector"> 
하나의 선택에

1) 설정 목록보기

3) android:state_activatedandroid:state_selected 변경 :

사용
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@color/list_item_selected_color" 
     android:state_activated="true"/> 
    <item android:drawable="@color/list_item_default_color"/> 
</selector> 

4) 강조 항목 listView.setItemChecked(index, true);

참고 :은 분명히 뷰의 상태에 대해 특별히 state_activated 당신이 this post을 확인할 수 있도록하려면, 그것은 흥미 롭습니다.

+0

불행히도 API-7을 사용하며 state_activated가 없습니다. –

+0

그러면 내 생각에 네 길은 유일한 길이다. – tachyonflux

0

색상이 약간 혼동되었습니다.

고정 OnItemClickListener : OnItemClickListener와의 getView 모두에서 직접 배경 색상을 설정하여 나의 선택이 안정적으로 작동하고 바보 같은 실수를 수정 한 후

public void onItemClick(AdapterView<?> parent, final View view, final int position, 
     long id) { 
    categoriesAdapter.setSelectedPosition(position); 
    for (int j = 0; j < parent.getChildCount(); j++) { 
     parent.getChildAt(j).setSelected(false); 
     parent.getChildAt(j).setBackgroundColor(getContext().getResources().getColor(
      R.color.list_item_default_color)); 
    } 
    view.setBackgroundColor(getContext().getResources().getColor(
     R.color.list_item_selected_color)); 

    // More code here 
} 

고정 어댑터 :의

private Integer selectedPosition; 

public void setSelectedPosition(int position) { 
    this.selectedPosition = position; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    TextView label = (TextView) View.inflate(context, textViewResourceId, null); 
    label.setText(getName(values.get(position))); 
    if(selectedPosition != null) { 
     if(position == selectedPosition) { 
      label.setBackgroundColor(context.getResources() 
       .getColor(R.color.list_item_selected_color)); 
     } else { 
      label.setBackgroundColor(context.getResources() 
       .getColor(R.color.list_item_default_color)); 
     } 
    } 
    return label; 
} 

그래서, 방법 안드로이드가 위젯 상태를 안정적으로 바꿀 수 없기 때문에 <selector>으로이 작업을 수행 할 수 없습니다. 맞습니까? 아니면 누군가 "<selector> way"가 작동하고 있습니까? 11 + API에 대한