Why isn't an Adapter with cached buttons working as expected in Android?

女生的网名这么多〃 提交于 2019-12-11 17:47:47

问题


Edit3: Exchanged the code for a complete runnable test case.

Edit2: Added some code that updates the number of buttons after five seconds. When this happens the buttons becomes unclickable no matter what layout you use.

Edit1: It seems this is depending on the Layout used for the ListView. I will investigate further.

I want to create the buttons once, i.e. cache them. I can't use the provided convertView and edit it for various reasons (every row will in the end contain a couple of components, all created by another framework).

If I create an Adapter like below, which seems very reasonable and imo should work, only buttons that have been outside the ListView, and are scrolled back in, are clickable.

It seems the button's clickable area isn't set correctly on first display. Can anyone explain why?

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;

public class TestActivity extends Activity
{
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        final ListView listView = new ListView(this);

        final ArrayList<View> cachedButtons = new ArrayList<View>(Arrays.asList(new View[20]));

        listView.setAdapter(new BaseAdapter() {
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (cachedButtons.get(position) == null) {
                    Button b = new Button(parent.getContext());
                    b.setText("Button " + position);
                    b.setClickable(true);
                    cachedButtons.set(position, b);
                }
                return cachedButtons.get(position);
            }

            public int getCount() { return cachedButtons.size(); }
            public Object getItem(int position) { return null; }
            public long getItemId(int position) { return position; }
        });

        // Add a new button after five seconds
        new Timer().schedule(new TimerTask() {
            public void run()
            {
                runOnUiThread(new Runnable() {
                    public void run()
                    {
                        cachedButtons.addAll(Arrays.asList(new View[1])); // Add one more
                        ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged();
                        Toast.makeText(listView.getContext(), "Now you can't press the buttons anymore", 0).show();
                    }
                });
            }
        }, 5000);

        // Doesn't work with these lines
        LinearLayout layout = new LinearLayout(this);
        layout.addView(listView);
        setContentView(layout);

        // Works with this, so no Layout works.
        //setContentView(layout);
    }
}

回答1:


I think Android is reusing your views so that is causing you problems .I suggest you use a view holder .It is a static class that holds the view for you.See this tutorial




回答2:


The answer was quite simple, yet eluded me for many hours. Just override getItemViewType and the views won't be recycled. At least it seems to work for now. I still find the JavaDocs confusing on this.

public int getItemViewType(int position)
{
    return AdapterView.ITEM_VIEW_TYPE_IGNORE;
}


来源:https://stackoverflow.com/questions/10152908/why-isnt-an-adapter-with-cached-buttons-working-as-expected-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!