listView中的Item有时候会添加其他的内容,例如有一块儿隐藏的区域,点击后展开,再次点击则隐藏。这时如果Item超过一屏,那么直接在Adapter中的getView方法加入判空操作,即
if(convertView == null){
convertView = new DownloadItem_CachedView(context);
}
这时候,可能会出现混乱显示的情况。
解决办法,有三种。
1. 首先,各位想到的可能是直接把判空操作去掉,那么就不会复用,也就不会出现混乱了。这确实是一种方法,但是生成的View没有复用,那么会造成资源的浪费,而且有时候如果程序复杂,会出现各种异常的情况,这就是无意中造就的Bug,而且解的时候很难发现,本人就深深受过这种坑害。
2. 本地点击状态记录。传过去list的时候,加入一个字段表示是否已经展开,在原数据上加字段,该方法最好。举个例子:假如之前list传的是1-20的数字,每一个都显示在Item上,之前的 数据是list<Integer>,那么现在改成list<Map<Integer,Boolean>>,用来记录是否应该被展开,然后每次getView的时候判断是否该显示出来。
代码如下:
MainActivity.java
public class MainActivity extends Activity implements OnItemClickListener{
private ListView lv;
private Map<Integer,Boolean> ItemString;
private ListViewAdapter myAdapter ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv= (ListView) findViewById(R.id.listview);
initItemNum();
myAdapter = new ListViewAdapter(MainActivity.this,ItemString);
lv.setAdapter(myAdapter);
lv.setOnItemClickListener(this);
}
private void initItemNum() {
// TODO Auto-generated method stub
ItemString = new HashMap<Integer,Boolean>();
for(int i =0;i<20;i++){
ItemString.put(i,false);
}
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, final int arg2, long arg3) {
View view = arg1.findViewById(R.id.bottom);
if(view.getVisibility() == View.VISIBLE){
view.setVisibility(View.GONE);
ItemString.put(arg2, false);
}
else{
view.setVisibility(View.VISIBLE);
ItemString.put(arg2, true);
}
Toast.makeText(MainActivity.this, "你点击的是:"+arg2, Toast.LENGTH_SHORT).show();
}
}
listViewAdapter.java
public class ListViewAdapter extends BaseAdapter {
private Context context;
private Map<Integer,Boolean> ItemNumString;
private LayoutInflater inflater;
public ListViewAdapter(Context context,Map<Integer,Boolean> ItemNumString) {
this.context = context;
this.ItemNumString = ItemNumString;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return ItemNumString.size();
}
@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return ItemNumString.get(arg0);
}
@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
}
@Override
public View getView(final int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
if(arg1 == null){
arg1 = inflater.inflate(R.layout.listview_item, null);
}
else{
boolean flag = ItemNumString.get(arg0);
if(flag){
arg1.findViewById(R.id.bottom).setVisibility(View.VISIBLE);
}
<span style="background-color: rgb(51, 255, 51);">else{
arg1.findViewById(R.id.bottom).setVisibility(View.GONE);
}//重点,虽然默认为Gone,但复用的时候要加上,否则会混乱。</span>
}
return arg1;
}
}
注意:可以将view想象成白板,每次重用需要将白板檫干净再用,否则在写了字的白板上再写字,那么就乱掉啦。
3.用全局map来记录点击状态。初始化Adapter的时候,初始化map,点击状态改变时,再次记录map中,getView的时候加入判断即可。这样做省事,但是浪费资源,而且有时候回有危险,就是刷新状态的时候,需要重新初始化map。
好了,就记录到这。