android - 带复选框的 ListView 在滚动时变形

标签 android listview android-listview

我有一个包含 Checkable 项目的 ListView 的 Activity 。每个项目都是一个自定义 View 名称 CheckableContact,它实现了 Checkable。一切正常,除非我向下滚动 ListView 中的项目以不同的速度移动并且不在适当的位置。查看下面的屏幕截图。
需要记住的是,ListView 在滚动结束时使用 sociket.io 进行更新。

ListView distorted ListView distorted

这是我的类(class)的完整来源。

CheckableContact.java

public class CheckableContact extends LinearLayout implements Checkable {
    private final View v;
    private ImageView imageView;
    private TextView name;

    public int getProfileID() {
        return profileID;
    }

    public void setProfileID(int profileID) {
        this.profileID = profileID;
    }

    private int profileID;

    public TextView getDesc() {
        return desc;
    }

    public TextView getName() {
        return name;
    }

    public ImageView getImageView() {
        return imageView;
    }

    private TextView desc;
    boolean checked = false;

    public CheckableContact(Context context) {
        super(context);
        LayoutInflater inflater = LayoutInflater.from(context);
        v = inflater.inflate(R.layout.contact_item_check, this, true);
        CheckBox cb = (CheckBox) v.findViewById(R.id.select_contact);
        cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                setChecked(b);
            }
        });

        imageView = (ImageView) v.findViewById(R.id.avatar);
        name = (TextView) v.findViewById(R.id.contact_title);
        desc = (TextView) v.findViewById(R.id.contact_desc);
    }


    @Override
    public void setChecked(boolean b) {
        Log.d("Checkable", "Checking: " + profileID);
        this.checked = b;
    }

    @Override
    public boolean isChecked() {
        return checked;
    }

    @Override
    public void toggle() {
        checked = !checked;
    }
}

CheckParticipantsAdapter.java

public class CheckParticipantsAdapter extends ArrayAdapter<Profile> {
    LayoutInflater inflater;
    ArrayList<Profile> myProfiles;
    AQuery aq;
    private Context context;
    int contactLayout = R.layout.conversation_item;
    Map<Integer, CheckableContact> checks = new HashMap<>();

    public CheckParticipantsAdapter(Context context, ArrayList<Profile> myProfiles) {
        super(context, R.layout.friend_list, myProfiles);
        this.myProfiles = myProfiles;
        this.context = context;
        aq = new AQuery(context);

    }

    public void setContactLayout(int layoutID) {
        contactLayout = layoutID;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        Profile profile = myProfiles.get(position);
        if (row == null) {
            row = new CheckableContact(context);

            ((CheckableContact) row).getName().setText(profile.getFullName());

            ((CheckableContact) row).setProfileID(profile.getProfileID());
            if (checks.containsKey(profile.getProfileID())) {
                ((CheckableContact) row).setChecked(checks.get(profile.getProfileID()).isChecked());
            } else {
                checks.put(profile.getProfileID(), (CheckableContact) row);
            }
        } else {
            row = checks.get(profile.getProfileID());
        }


//        TextView username = (TextView) row.findViewById(R.id.conversation_name);

//        if (!profile.getPhotoPath().equals("")) {
        String path = Util.URL_USERS_PHOTOS + profile.getPhotoPath();
        aq.id(((CheckableContact) row).getImageView()).image(path, true, true, 100, R.drawable.avatar);
//        }

        return row;
    }

    public ArrayList<Integer> getCheckIds() {
        ArrayList<Integer> ids = new ArrayList<>();
        Iterator it = checks.keySet().iterator();
        while (it.hasNext()) {
            CheckableContact c = (CheckableContact) it.next();
            if (c.isChecked()) {
                ids.add(c.getProfileID());
            }
        }
        return ids;
    }
}

最佳答案

当您在列表项中使用自定义 View 时,我认为您的 View 不知道自己的高度,因此在滚动时您会看到不同的 View 高度,因为您一直在创建新 View ,因此您必须使用 ViewHolder 以获得更好的性能和修复你的问题。

您可以查看以下链接以更好地理解我的话,我也为您提供了一些示例代码。

ListView with ArrayAdapter and ViewHolder

Android Developer

所有步骤是:

1- 当 convertView 为 null 时初始化你的 View

2- 使用setTag 方法在 View 中存储此信息

3- 如果您的 convertView 不为空,则使用 getTag 获取该信息

4- 在 else 部分之后初始化 View 的数据。

if (convertView == null)
{
   ViewHolder holder = new ViewHolder();
   .....  // init holder


   convertView.setTag(holder);

}

else
{
   holder = (ViewHolder)convertView.getTag();
} 

 // init data with holder object

关于android - 带复选框的 ListView 在滚动时变形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27645750/

相关文章:

java - 从布局中包含的 ListView 接收字符串。安卓

WPF ListView 变得比它包含的 Canvas 更大

android - 从android中的10,000个项目列表中选择任何项目

java - ListView 页脚导致 ArrayIndexOutOfBoundsException

android - 如何检测应用程序是否已关闭/退出

android - windows下eclipse安卓模拟器的SD卡在哪里?

java - 连接到模拟器服务器的多个模拟器客户端

java - 如何在不创建字符串资源的情况下使用十进制数

xaml - 如何在 ListView DataTemplate 中设置行高

c# - 从 DataTable 填充 ListView