在 ListView 中滚动时 CheckedTextView 消失

Posted

技术标签:

【中文标题】在 ListView 中滚动时 CheckedTextView 消失【英文标题】:CheckedTextView disappears when scroll in ListView 【发布时间】:2015-04-27 04:39:32 【问题描述】:

我有自定义 ListView。我正在使用数组适配器来填充我的 ListViews 行。它工作得很好。当我选择 ListView 行时,我的 checkedtextview 变得可见。滚动我检查的情况后消失。 我怎样才能记住我的支票?

感谢您的帮助。

这是我的适配器

package test.cbsmobil.ibb;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.TextView;

import java.util.ArrayList;


public class ListViewItemsAdapter extends ArrayAdapter<Item> 

private Context context;
private ArrayList<Item> items;
private LayoutInflater vi;
private int resLayout;
private CheckedTextView ctv;
private int selectedIndex;


public ListViewItemsAdapter(Context context, ArrayList<Item> items) 
    super(context, 0, items);
    this.context = context;
    this.items = items;
    vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    selectedIndex = -1;






@Override
public long getItemId(int position) 

    return position;


@Override
public View getView(int position, View convertView, ViewGroup parent) 
    View v = convertView;


    final Item i = items.get(position);
    if (i != null) 
        if (i.isSection()) 
            ListViewItemsSection si = (ListViewItemsSection) i;
            v = vi.inflate(R.layout.list_item_section, null);

            v.setOnClickListener(null);
            v.setOnLongClickListener(null);
            v.setLongClickable(false);

            final TextView sectionView = (TextView) v.findViewById(R.id.list_item_section_text);
            sectionView.setText(si.getTitle());
         else 

            ListViewItems ei = (ListViewItems) i;
            v = vi.inflate(R.layout.list_item_entry,null);

            final TextView title = (TextView) v.findViewById(R.id.list_item_entry_title);

            if (title != null)
                title.setText(ei.title);

        
    

    return v;




 

这是我的 MainActivity; 让我解释一下这个活动代码块。 layerlist 是我的 ListView。我在 ListView 中使用多项选择模式进行多项选择。

layerlist.setAdapter(adapter);
    layerlist.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);

    layerlist.setOnItemClickListener(new AdapterView.OnItemClickListener() 
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
            if(!items.get(position).isSection())


                    ListViewItems item = (ListViewItems) items.get(position);
                    //adapter.setSelectedIndex(position);
                    Log.d("ListView", "Position " + item.toString());
                    //View v = layerlist.getChildAt(position);
                    View v = getViewByPosition(position,layerlist);
                    CheckedTextView ctv = (CheckedTextView) v.findViewById(R.id.ctv);



                    if (!ctv.isChecked()) 
                        ctv.setChecked(true);
                        Log.d("Checked", "Açıldı" + " " + ctv.isChecked());

                     else 
                        ctv.setChecked(false);
                        Log.d("Checked", "Kapandı" + " " + ctv.isChecked());
                    


           
        
    );



    return rootView;


private View getViewByPosition(int pos, ListView listView) 
    final int firstListItemPosition = listView.getFirstVisiblePosition();
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;

    if (pos < firstListItemPosition || pos > lastListItemPosition ) 
        return listView.getAdapter().getView(pos, null, listView);
     else 
        final int childIndex = pos - firstListItemPosition;
        return listView.getChildAt(childIndex);
    

【问题讨论】:

【参考方案1】:

您应该使用developer.android.com 中描述的“视图持有者”设计模式,并在this post 上进行了详细说明。

这里最重要的是:

    创建 ViewHolder 类; 如果 convertView 为空,则将 ViewHolder 实例存储在标签中; 如果不是,则从标签中恢复 ViewHolder 实例。

这是我的适配器的代码:

package br.com.inovant.pm;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import java.util.List;

public class ContactsAdapter extends ArrayAdapter<CheckedContact>

    public ContactsAdapter(Context context, List<CheckedContact> contacts) 
        super(context, 0, contacts);
    

    static class ViewHolder 
        protected CheckedTextView checkedTextView;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        ViewHolder viewHolder;
        if (convertView == null) 
            convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.select_dialog_multichoice, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.checkedTextView = (CheckedTextView) convertView.findViewById(android.R.id.text1);
            convertView.setTag(viewHolder);
         else 
            viewHolder = (ViewHolder) convertView.getTag();
        

        final CheckedContact checkedContact = getItem(position);

        final CheckedTextView checkedTextView = viewHolder.checkedTextView;
        checkedTextView.setText(checkedContact.getContact().getDisplayName());
        checkedTextView.setChecked(checkedContact.isChecked());
        return convertView;
    

    @Override
    public long getItemId(int position) 
        return getItem(position).getContact().getId().hashCode();
    

    @Override
    public boolean hasStableIds() 
        return true;
    

【讨论】:

【参考方案2】:

我遇到了同样的问题,所以我在自定义适配器中使用了以下方法,我得到了解决方案。

在您的 ListViewItemsAdapter 中添加以下方法:

@Override
    public int getCount() 
        return alUpgradeTour.size();
    

    @Override
    public int getItemViewType(int position) 
        return position;
    

    @Override
    public int getViewTypeCount() 

        return getCount();
    

试试看,你也会得到解决的。

【讨论】:

我没有得到解决方案。 :( 我将 alUpgradeTour.size 更改为我的 arrayadapter 大小。但我买不起。【参考方案3】:

Android 的 ListView 会回收其所有单独的视图,也就是说,当一个列表项从屏幕上滚出时,它的视图会被回收以供刚刚滚动到可见屏幕区域的视图使用。现在,当一个较旧的列表项滚动回视图时,它会获得一些其他回收的视图来绘制自己。 因此,复选标记丢失或任何已更改/更新的数据。

解决方案是您将更改保存在列表项中,在您的情况下 - ListViewItems。假设您在 ListViewItems 的类定义和调用 setChecked 方法的 onItemClick 中有一个标志 boolean isChecked = false,设置 isChecked = true 这将帮助您保留复选标记。

希望对你有帮助。

【讨论】:

以上是关于在 ListView 中滚动时 CheckedTextView 消失的主要内容,如果未能解决你的问题,请参考以下文章

在 ListView 中,向下滚动时,在颤动中丢失数据

WPF:如何在拖动 ListView 项目时允许在 ListView 中使用鼠标滚轮滚动?

在 ListView 中滚动时 CheckedTextView 消失

更新新项目时如何在 WinForms ListView 控件中自动向下滚动?

在android中滚动listView时重新加载图像

在 Flutter 中使用 InheritedWidget 时 ListView 失去滚动位置