Android 具有自定义适配器状态持久性的ListView

Android 具有自定义适配器状态持久性的ListView,android,android-listview,custom-adapter,Android,Android Listview,Custom Adapter,我有一个带有自定义适配器的列表视图。自定义适配器只是TextView和2个ImageButtons。 单击ImageButton时,我希望其图像切换。但是,当我向下滚动时,一些随机项也会被切换 所以我认为这与屏幕上项目位置的相对性有关。因此,我为每个ImageButton分配了一个标记,该标记对应于它在列表视图中的位置。然后,我使用以下代码正确选择必要的项目: int firstVisiblePos = listView.getFirstVisiblePosition(); in

我有一个带有自定义适配器的列表视图。自定义适配器只是TextView和2个ImageButtons。 单击ImageButton时,我希望其图像切换。但是,当我向下滚动时,一些随机项也会被切换

所以我认为这与屏幕上项目位置的相对性有关。因此,我为每个ImageButton分配了一个标记,该标记对应于它在列表视图中的位置。然后,我使用以下代码正确选择必要的项目:

    int firstVisiblePos = listView.getFirstVisiblePosition();
    int viewPos = 0;
    int position = Integer.parseInt(v.getTag().toString());
    Toast.makeText(this, v.getTag().toString(), Toast.LENGTH_SHORT).show();
    for (int i = 0; i < listView.getChildCount(); i++) {
        viewPos = firstVisiblePos + i;
        if (viewPos == position) {              
            relativeLayout = (RelativeLayout) listView.getChildAt(position);
            break;
        }
    }
int firstVisiblePos=listView.getFirstVisiblePosition();
int-viewPos=0;
int position=Integer.parseInt(v.getTag().toString());
Toast.makeText(this,v.getTag().toString(),Toast.LENGTH_SHORT).show();
对于(int i=0;i
然而,我仍然经历着同样的行为。 感谢您的帮助

UPD:

公共类CustomAdapter扩展了BaseAdapter{
私有数组列表数据;
私人活动;
私人充气机;
公共CustomAdapter(活动、ArrayList数据){
this.myActivity=活动;
这个数据=数据;
this.inflater=(LayoutInflater)myActivity
.getSystemService(上下文布局\充气机\服务);
}
@凌驾
public int getCount(){
返回data.size();
}
@凌驾
公共对象getItem(int位置){
返回数据。获取(位置);
}
@凌驾
公共长getItemId(int位置){
返回位置;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
if(convertView==null){
convertView=充气机。充气(R.layout.list_行,空);
}
TextView谚语=(TextView)convertView.findViewById(R.id.title);
setText(data.get(position));
setextsize(android.util.TypedValue.COMPLEX\u UNIT\u SP,14);
谚语.设置字体(MainActivity.tf,1);
ImageButton favBtn=(ImageButton)convertView.findViewById(R.id.btn_收藏夹);
if(MainActivity.favorites.contains(data.get(position))){
//收藏夹,设置fav图标
setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));
}       
favBtn.setTag(位置);
返回视图;
}
}像这样试试

首先创建一个模型来存储值并检查Favurite

public class Data {

private String value;
private boolean favurite;

public Data(String value,boolean favurite){
    this.value=value;
    this.favurite=favurite;
}
public String getValue() {
    return value;
}
public void setValue(String value) {
    this.value = value;
}
public boolean isFavurite() {
    return favurite;
}
public void setFavurite(boolean favurite) {
    this.favurite = favurite;
}
}

然后在
活动中将其更改为
ArrayList
,而不是创建
ArrayList

ArrayList<Data> list=new ArrayList<Data>();
        list.add(new Data("value1", false));
        list.add(new Data("value2", false));
ArrayList list=new ArrayList();
添加(新数据(“值1”,假));
添加(新数据(“值2”,假));
并将其传递给CustomAdapter类

我更改了您的适配器类以使其正常工作

public class CustomAdapter extends BaseAdapter {
    private ArrayList<Data> data;
    private Activity myActivity;
    private LayoutInflater inflater;

    public CustomAdapter(Activity activity, ArrayList<Data> data) {
        this.myActivity = activity;
        this.data = data;
        this.inflater = (LayoutInflater) myActivity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }


@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.list_row, null);
    }
    final Data d=data.get(position);
    TextView proverb = (TextView) convertView.findViewById(R.id.title);
    proverb.setText(d.getValue());
    proverb.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
    proverb.setTypeface(MainActivity.tf, 1);
    final ImageButton favBtn = (ImageButton) convertView.findViewById(R.id.btn_favorite);

    if(d.isFavurite())
        favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));    
    else
        favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.Non_fav));

    favBtn.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View arg0) {
            d.setFavurite(true);
            favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));    
            notifyDataSetChanged();
        }
    });
    return convertView;
}
公共类CustomAdapter扩展了BaseAdapter{
私有数组列表数据;
私人活动;
私人充气机;
公共CustomAdapter(活动、ArrayList数据){
this.myActivity=活动;
这个数据=数据;
this.inflater=(LayoutInflater)myActivity
.getSystemService(上下文布局\充气机\服务);
}
@凌驾
public int getCount(){
返回data.size();
}
@凌驾
公共对象getItem(int位置){
返回数据。获取(位置);
}
@凌驾
公共长getItemId(int位置){
返回位置;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
if(convertView==null){
convertView=充气机。充气(R.layout.list_行,空);
}
最终数据d=数据获取(位置);
TextView谚语=(TextView)convertView.findViewById(R.id.title);
setText(d.getValue());
setextsize(android.util.TypedValue.COMPLEX\u UNIT\u SP,14);
谚语.设置字体(MainActivity.tf,1);
最终ImageButton favBtn=(ImageButton)convertView.findViewById(R.id.btn_收藏夹);
if(d.isFavurite())
setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));
其他的
setImageDrawable(myActivity.getResources().getDrawable(R.drawable.Non_fav));
favBtn.setOnClickListener(新的OnClickListener(){
@凌驾
公共void onClick(视图arg0){
d、 setFavurite(真);
setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));
notifyDataSetChanged();
}
});
返回视图;
}
}


希望这能解决您的问题。

问题在于,当用户在listview中滚动时,列表项会被重复使用。因此,每次都必须基于数据重新生成列表项。如果项目是收藏夹,则看起来您正在更改图像,但如果项目不是收藏夹,则不会将其更改回原来的状态

试着改变

if(MainActivity.favorites.contains(data.get(position))){
    // favorite, set fav icon
    favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));         
}


我假设当您单击图像按钮时,它会将
data.get(position)
添加到
main activity.favorites
并在再次单击时将其删除

做一件事,,,不要检查convertView的空值,直接一个接一个地编码,,,如下所示

     @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        convertView = inflater.inflate(R.layout.list_row, null);


    TextView proverb = (TextView) convertView.findViewById(R.id.title);
    proverb.setText(data.get(position));
    proverb.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
    proverb.setTypeface(MainActivity.tf, 1);
    ImageButton favBtn = (ImageButton) convertView.findViewById(R.id.btn_favorite);
    if(MainActivity.favorites.contains(data.get(position))){
        // favorite, set fav icon
        favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));         
    }       
    favBtn.setTag(position);
    return convertView;
}

发布自定义适配器的getView()方法。从getView()不清楚,所以发布完整的适配器类。实际上,它是在我这边发现的,,,当我们每次膨胀视图时,listview中的滚动切换问题将得到解决。它解决了最初的问题,但现在我得到了空指针异常。我得到了完全有效的解决方案,结合了你的答案和阿米特·古普塔的答案。谢谢。我介绍了您建议的更改。但是,我没有创建新的数据类。它起作用了。谢谢。
if(MainActivity.favorites.contains(data.get(position))){
    // favorite, set fav icon
    favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));         
} else {
    // not favorite, set default icon
    favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.notfav));
}
     @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        convertView = inflater.inflate(R.layout.list_row, null);


    TextView proverb = (TextView) convertView.findViewById(R.id.title);
    proverb.setText(data.get(position));
    proverb.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
    proverb.setTypeface(MainActivity.tf, 1);
    ImageButton favBtn = (ImageButton) convertView.findViewById(R.id.btn_favorite);
    if(MainActivity.favorites.contains(data.get(position))){
        // favorite, set fav icon
        favBtn.setImageDrawable(myActivity.getResources().getDrawable(R.drawable.fav));         
    }       
    favBtn.setTag(position);
    return convertView;
}