Android Listview:用于隐藏行中控件的按钮

时间:2012-12-20 16:30:37

标签: android listview adapter recycle

我遇到了listview和ArrayAdapter的问题。 我的目标是在每一行上都有一个按钮,允许用户隐藏(或显示)此行中包含的TextView。

但是当我测试我的代码时,如果我单击第一行的按钮,它会隐藏第一个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 个答案:

答案 0 :(得分:2)

在代码中很难找到问题。

您正在重复使用ViewHolder,这非常好,因为它可以节省您每次重新分配新内存的时间。

代码中的问题是:您没有重置TextView的可见性,导致重用的View将继承任何其他TextView的可见性设置的问题。

为了解决这个问题,您必须将每个项目的可见性与项目本身一起存储在适配器中,并在恢复视图时重新加载可见性设置。

而不是String我会使用

class AGoodClassName {
String s; boolean b;
}

哪个存储在适配器中。只要可见性发生变化,您就需要更新b

答案 1 :(得分:0)

旧线程,但它适用于我,因为我只需要在ListView的某些列表项中显示按钮。

如果有人指向此...这是我用来仅显示我列表中某些项目中的按钮的代码!

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.

记录我正在使用ButterKnife!

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