防止listView项目ImageButton更改滚动状态。并防止其他ImageButton由于一个ImageButton而更改状态

时间:2018-11-24 09:11:10

标签: android listview

我正在创建一种 DataSet_Collector 应用程序,该应用程序在ListView中向用户显示其对话线程。用户选择垃圾邮件线程。这些线程将被发送到Excel工作表。然后显示其余的线程(非垃圾邮件),用户选择他要发送的那些线程。 到目前为止,我已经使用扩展的LinkedHashMap<String, String>(即 ListView )显示了存储在SimpleAdapterThreadsAdapter中的线程。 Key中的LinkedHashMap<>发件人,而Value处的Key线程。我创建了一个名为listView_layout_item.xml的布局,其中包含两个TextView和一个ImageButtonitem中的每个ListViewlistView_layout_item.xml中用getView()进行膨胀,如下所示。

ThreadsAdapter.java

public class ThreadsAdapter extends SimpleAdapter {

    private Context context;

    /**
     * Constructor
     *
     * @param context  The context where the View associated with this SimpleAdapter is running
     * @param data     A List of Maps. Each entry in the List corresponds to one row in the list. The
     *                 Maps contain the data for each row, and should include all the entries specified in
     *                 "from"
     * @param resource Resource identifier of a view layout that defines the views for this list
     *                 item. The layout file should include at least those named views defined in "to"
     * @param from     A list of column names that will be added to the Map associated with each
     *                 item.
     * @param to       The views that should display column in the "from" parameter. These should all be
     *                 TextViews. The first N views in this list are given the values of the first N columns
     */
    ThreadsAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
        super(context, data, resource, from, to);
        //This 'data' is an ArrayList() of LinkedHashMap<String, String>
        //first String for sender of the thread, second String for the thread
        //ListView will list sender as item and thread as subitem in 
        //every getView() instance
        this.context = context;
    }


    private class ViewHolder{
        private ImageButton threadCheck;
        private boolean isTChecked;
    }

    @SuppressLint("InflateParams")
    @Override
    public View getView(final int position, View convertView,
                        ViewGroup parent) {
        ViewHolder view;
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.listView_layout_item, null);
            view = new ViewHolder();
            view.threadCheck =(ImageButton) convertView.findViewById(R.id.threadChecker);
            view.isTChecked = false; // in the start of the app.
            final ViewHolder finalView = view;
            view.threadCheck.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(finalView.isTChecked)
                        finalView.threadCheck.setImageResource(R.drawable.circle_unchecked);
                    else
                        finalView.threadCheck.setImageResource(R.drawable.circle_checked);
                    finalView.isTChecked = !finalView.isTChecked;
                }
            });
            convertView.setTag(view);
        } else {
            view = (ViewHolder) convertView.getTag();
        }
        super.getView(position, convertView, parent);
        return convertView;
    }
}

super.getView()getView()的末尾被调用,因为我想使用 Text Subtext SimpleAdapter的{​​{1}}格式。

使用给定的代码

当我单击ListView项目中的一个ImageButton来更改其状态时,ListView中其他项目中的其他ImageButtons也将更改其状态。 为什么?!以及如何解决?

当我向上或向下滚动时,任何ListView的状态都会随机变化。 为什么?!以及如何解决?

我是ImageButtonListView适配器的新手。当前的答案没有意义,所以我发布了自己的特殊问题。

1 个答案:

答案 0 :(得分:0)

在ListViews中,行(在您的情况下为ViewHolders)被回收再利用,这意味着您看到的东西在上下移动,但是相同的行又一次又一次地重复。

请记住,将任何状态存储在行中是不正确的,因为当重新使用东西时,它们将使用以前拥有的状态,乍一看似乎是随机的。

您应该做的是在数据中存储isTChecked状态。为此,我建议您将LinkedHashMap切换为ArrayList并使用简单的Java对象。您可以拥有这样的课程:

public class ConversationThread {
    public String sender;
    public String thread;
    public Boolean isChecked = false; /* Initially false, to match your scenario. */
}

您的适配器的getView替代将变成这样:

public View getView(final int position, View convertView, ViewGroup parent) {
    /* 'getItem' would bring you the data for the provided position, once you 
     * switch from a LinkedHashMap to an ArrayList. */
    final ConversationThread conversationThread = getItem(position);

    ViewHolder view;

    if (convertView == null) {
        /* Here, the row is created for the first time, hence why you inflate
         * the XML layout. */
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();
        convertView = inflater.inflate(R.layout.listView_layout_item, null);

        view = new ViewHolder();
        view.threadCheck = (ImageButton) convertView.findViewById(R.id.threadChecker);

        /* You save the ViewHolder as the View's tag, to be able to reuse it. */
        convertView.setTag(view);
    } else {
        /* Here, the row exists, so you fetch the ViewHolder to actually reuse it. */
        view = (ViewHolder) convertView.getTag();
    }

    /* Once you have your ViewHolder, old or new, you can then update it.
     * That means updating the image and using a new click listener as well. */
    if (conversationThread.isChecked)
        view.threadCheck.setImageResource(R.drawable.circle_checked);
    else
        view.threadCheck.setImageResource(R.drawable.circle_unchecked);

    view.threadCheck.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v /* This is the actual view clicked (view.threadCheck) */) {
            /* On click, toggle the flag and then update the View. */
            conversationThread.isChecked = !conversationThread.isChecked;

            if (conversationThread.isChecked)
                v.setImageResource(R.drawable.circle_checked);
            else
                v.setImageResource(R.drawable.circle_unchecked);
        }
    });

    /* If you also need to call super, you can do so. */
    super.getView(position, convertView, parent);

    return convertView;
}

这绝不是最佳选择,我只是试图通过尽可能少地移动代码来使事情变得清晰。