2012-12-20 2 views
2

listview 및 ArrayAdapter에 문제가 있습니다. 내 목표는 각 행에 사용자가이 행에 포함 된 TextView를 숨기거나 표시 할 수있게하는 버튼을 갖는 것입니다.Android Listview : 행의 컨트롤을 숨기는 버튼

그러나 코드를 테스트 할 때 첫 번째 행의 버튼을 클릭하면 첫 번째 TextView뿐만 아니라 아래의 다른 TextView 9 행이 숨겨집니다.

정상적인 재활용 메커니즘 작업이라고 상상해 봅니다. 그러나 onClick 메서드에서 View 매개 변수가 고유하다고 가정 했으므로 실제로 이해하지 못합니다.

adapter_test.xml :

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_height="wrap_content" 
    android:layout_width="fill_parent" 
    android:padding="5dip"> 

     <ImageButton 
      android:id="@+id/adapter_test_button_showhide"  
      android:layout_height="wrap_content" 
      android:layout_width="wrap_content"    
      android:layout_alignParentLeft="true"   
      android:src="@drawable/ic_action_pause_light"> 
     </ImageButton>    
     <!-- label --> 
     <TextView android:id="@+id/adapter_test_text_label" 
       android:layout_width="fill_parent" 
       android:layout_height="wrap_content" 
       android:layout_toRightOf ="@id/adapter_test_button_showhide"> 
     </TextView>    
</RelativeLayout> 

AdapterTest.java

public class AdapterTest extends ArrayAdapter<String> 
{  

    // Holder 
    static class ViewHolder {TextView txtLabel ; ImageButton btnShowHide;} 

    //Initialize adapter 
    public AdapterTest(Context context, int resource, List<String> items) {super(context, resource, items);} 


    @Override 
    public View getView(int position, View v, ViewGroup parent) 
    {    
     // view Holder   
     ViewHolder viewHolder; 

     //Inflate the view 
     if(v==null) 
     { 
      //linearView = new LinearLayout(getContext()); 
      LayoutInflater li = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      v = li.inflate(R.layout.adapter_test, null); 

      // Create holder 
      viewHolder = new ViewHolder(); 
      viewHolder.txtLabel = (TextView)v.findViewById(R.id.adapter_test_text_label); 
      viewHolder.btnShowHide = (ImageButton)v.findViewById(R.id.adapter_test_button_showhide); 
      v.setTag(viewHolder);    
     } 
     else 
     { 
      viewHolder = (ViewHolder) v.getTag(); 
     }   

     // Load screen with data; 
     LoadScreenFromItem (viewHolder,getItem(position)); 
     return v; 
    } 


    public void LoadScreenFromItem(ViewHolder viewHolder, String item) 
    {  
     // Remove handler 
     viewHolder.btnShowHide.setOnClickListener(null); 

     // Add handler 
     viewHolder.btnShowHide.setOnClickListener(handleOnClickShowHide()); 

     // Set textt 
     viewHolder.txtLabel.setText(item); 
    } 


    private View.OnClickListener handleOnClickShowHide() 
    { 
     return new View.OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       View parent = (View)v.getParent(); 
       TextView listserie = (TextView) parent.findViewById(R.id.adapter_test_text_label); 

       // hide or show label 
       if (listserie.isShown()) listserie.setVisibility(View.INVISIBLE); 
       else listserie.setVisibility(View.VISIBLE); 
      } 
     }; 
    } 
} 

질문 :

내 질문은 : 내가 원하는 것을 할 수있는 방법이 있나요 ?

답변

2

문제는 코드에서 찾기가 어렵습니다.

ViewHolder을 재사용하고 있습니다. 매번 새로운 메모리를 재 할당 할 시간이 절약되므로 매우 유용합니다.

코드의 문제는 TextView의 표시를 재설정하지 않기 때문에 재사용 된보기가 다른 TextView의 표시 여부 설정을 상속한다는 문제가 발생합니다.

버그를 해결하려면 각 항목의 가시성을 항목 자체와 함께 어댑터에 저장하고보기를 복원 할 때 가시성 설정을 다시로드해야합니다.

대신 String의 I는 어댑터에 저장되어있는

class AGoodClassName { 
String s; boolean b; 
} 

을 사용합니다. 공개 설정이 변경 될 때마다 b을 업데이트해야합니다.

+0

감사합니다. 정상적으로 작동합니다. 필자는 Item에 UI 상태를 저장하는 것에 대해 약간 혼란 스럽지만 수용 가능합니다. – Batrarri

+0

@Batrarri 클래스를 데이터 클래스와 UI 클래스로 나눌 수 있습니다. 부울은 UI 클래스에 있습니다. 나는 최고의 클래스 디자인에 관해 여기에서 확실하지 않다 – Till

0

오래된 스레드하지만 내 ListView의 일부 목록 항목에만 단추를 표시해야하므로 그것은 나를 위해 작동합니다.

누구에게도 해당되는 경우 ... 내 목록의 일부 항목에만 버튼을 표시하는 데 사용하는 코드입니다!

내가 ButterKnife을 사용하고 공식적으로

The problem in your code is: You are not resetting the visibility of the TextView, leading to the problem that a reused View will inherit the visibility settings of any other TextView.!

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder; 
    if(convertView == null) { 
     convertView = activity.getLayoutInflater().inflate(resource, parent, false); 
     holder = new ViewHolder(convertView); 
     convertView.setTag(holder); 
    } 
    holder = (ViewHolder) convertView.getTag(); 

    if(items.size() > 0) { 
     MyItem item = items.get(position); 
     holder.myButton.setVisibility(View.VISIBLE); 
     if(!item.hasButton()) { 
      holder.myButton.setVisibility(View.GONE); 
     } 
     holder.myButton.setFocusable(false); 
     holder.myButton.setClickable(false); 
    } 
    return convertView; 
} 

public class ViewHolder { 
    @InjectView(R.id.card_btn_layout) View myButton; 

    public ViewHolder(View view) { 
     ButterKnife.inject(this, view); 
    } 
}