列表适配器中的复选框行为异常
CheckBox in List Adapter acts strange
我有一个列表适配器,每个项目都有一个复选框。我还可以选择从该列表中删除用户检查的所有项目。
应该删除所选项目的部分运行良好,但是..
例如,如果我有
1. 0000
2. 5555
3. 9999
如果我选中 5555 和 9999,然后单击“删除”,它们就会消失,但是即使我没有按下它,0000 也会被选中。
(historyList是历史片段中的所有项目。listToRemove只是选中的项目)
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View view = inflater.inflate( R.layout.fragment_history, container, false );
adapter = new PasswordAdapter( historyList );
setListAdapter(adapter);
ImageView removeButton = ( ImageView ) view.findViewById( R.id.removeButton );
removeButton.setOnClickListener( new OnClickListener(){
@Override
public void onClick( View v )
{
if ( !listToRemove.isEmpty() )
{
listToRemove.clear();
adapter.updateList( historyList );
}
}
});
return view;
}
...
...
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
if (convertView == null)
{
result = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_list_item, parent, false);
}
else
{
result = convertView;
}
final Password item = getItem( position );
( (TextView) result.findViewById( R.id.historyPasswordTextView) ).setText(item.getPasswordString());
( (TextView) result.findViewById( R.id.historyDateTextView ) ).setText(item.getPasswordString());
CheckBox checkBoxToRemove = (CheckBox) result.findViewById( R.id.removePasswordFromHistoryCheckBox ) ;
checkBoxToRemove.setOnCheckedChangeListener( new OnCheckedChangeListener(){
@Override
public void onCheckedChanged( CompoundButton buttonView, boolean isChecked )
{
if( isChecked )
{
listToRemove.add( item );
// Log.d( "TAG", listToRemove.toString() );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after add: "+ listToRemove.get(i).getPasswordString());
}
else
{
listToRemove.remove( item );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after remove: "+ listToRemove.get(i).getPasswordString());
}
}
});
我是不是漏掉了什么?
像这样尝试也许有用
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_list_item, parent, false);
holder. checkBoxToRemove = (CheckBox) convertView.findViewById( R.id.removePasswordFromHistoryCheckBox ) ;
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
final Password item = getItem( position );
holder .checkBoxToRemove.setOnCheckedChangeListener( new OnCheckedChangeListener(){
@Override
public void onCheckedChanged( CompoundButton buttonView, boolean isChecked )
{
if( isChecked )
{
listToRemove.add( item );
// Log.d( "TAG", listToRemove.toString() );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after add: "+ listToRemove.get(i).getPasswordString());
}
else
{
listToRemove.remove( item );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after remove: "+ listToRemove.get(i).getPasswordString());
}
}
});
return convertView;
}
class ViewHolder {
CheckBox checkBoxToRemove;
}
然后在您的 getView 中添加:
if(listToRemove.contains(item){
holder.checkBoxToRemove.setChecked(true);
}else{
holder.checkBoxToRemove.setChecked(false);
}
我认为你不应该在 ListView
中使用复选框。您的问题可能是由于行视图被重用所致。我的意思是复选框可以来自以前的可见行(在您的示例中,删除后的第 0000 行,复选框可以是删除前的第 5555 行之一)。
我认为最好的方法是使用 onItemClickListener
。在您的 onItemClick
方法中,您从适配器的 listToRemove
添加或删除项目并调用 adapter.notifyDataSetChange()
.
并且在您的 getView
方法中,您根据 listToRemove
列表绘制行。
我有一个列表适配器,每个项目都有一个复选框。我还可以选择从该列表中删除用户检查的所有项目。 应该删除所选项目的部分运行良好,但是.. 例如,如果我有
1. 0000
2. 5555
3. 9999
如果我选中 5555 和 9999,然后单击“删除”,它们就会消失,但是即使我没有按下它,0000 也会被选中。
(historyList是历史片段中的所有项目。listToRemove只是选中的项目)
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View view = inflater.inflate( R.layout.fragment_history, container, false );
adapter = new PasswordAdapter( historyList );
setListAdapter(adapter);
ImageView removeButton = ( ImageView ) view.findViewById( R.id.removeButton );
removeButton.setOnClickListener( new OnClickListener(){
@Override
public void onClick( View v )
{
if ( !listToRemove.isEmpty() )
{
listToRemove.clear();
adapter.updateList( historyList );
}
}
});
return view;
}
...
...
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
if (convertView == null)
{
result = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_list_item, parent, false);
}
else
{
result = convertView;
}
final Password item = getItem( position );
( (TextView) result.findViewById( R.id.historyPasswordTextView) ).setText(item.getPasswordString());
( (TextView) result.findViewById( R.id.historyDateTextView ) ).setText(item.getPasswordString());
CheckBox checkBoxToRemove = (CheckBox) result.findViewById( R.id.removePasswordFromHistoryCheckBox ) ;
checkBoxToRemove.setOnCheckedChangeListener( new OnCheckedChangeListener(){
@Override
public void onCheckedChanged( CompoundButton buttonView, boolean isChecked )
{
if( isChecked )
{
listToRemove.add( item );
// Log.d( "TAG", listToRemove.toString() );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after add: "+ listToRemove.get(i).getPasswordString());
}
else
{
listToRemove.remove( item );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after remove: "+ listToRemove.get(i).getPasswordString());
}
}
});
我是不是漏掉了什么?
像这样尝试也许有用
public View getView(int position, View convertView, ViewGroup parent) {
final View result;
ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_list_item, parent, false);
holder. checkBoxToRemove = (CheckBox) convertView.findViewById( R.id.removePasswordFromHistoryCheckBox ) ;
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
final Password item = getItem( position );
holder .checkBoxToRemove.setOnCheckedChangeListener( new OnCheckedChangeListener(){
@Override
public void onCheckedChanged( CompoundButton buttonView, boolean isChecked )
{
if( isChecked )
{
listToRemove.add( item );
// Log.d( "TAG", listToRemove.toString() );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after add: "+ listToRemove.get(i).getPasswordString());
}
else
{
listToRemove.remove( item );
for( int i=0; i<listToRemove.size(); i++)
Log.d("TAG","checked after remove: "+ listToRemove.get(i).getPasswordString());
}
}
});
return convertView;
}
class ViewHolder {
CheckBox checkBoxToRemove;
}
然后在您的 getView 中添加:
if(listToRemove.contains(item){
holder.checkBoxToRemove.setChecked(true);
}else{
holder.checkBoxToRemove.setChecked(false);
}
我认为你不应该在 ListView
中使用复选框。您的问题可能是由于行视图被重用所致。我的意思是复选框可以来自以前的可见行(在您的示例中,删除后的第 0000 行,复选框可以是删除前的第 5555 行之一)。
我认为最好的方法是使用 onItemClickListener
。在您的 onItemClick
方法中,您从适配器的 listToRemove
添加或删除项目并调用 adapter.notifyDataSetChange()
.
并且在您的 getView
方法中,您根据 listToRemove
列表绘制行。