简体   繁体   中英

generate spinner from custom list adapter

I'm building an app for ordering food from a resturant. When a user selects an item I hit our server to retrieve a JSON package containing the options for that item. (ex: Bread: White, Wheat).

What I'm trying to do is use a custom list adapter to generate a list of all the options the user needs to select before adding the item to the cart. This is working well, except when I click on the spinner I get:

05-20 15:12:53.602: ERROR/AndroidRuntime(696): FATAL EXCEPTION: main
05-20 15:12:53.602: ERROR/AndroidRuntime(696): android.view.WindowManager$BadTokenException: Unable to add window -- token android.app.LocalActivityManager$LocalActivityRecord@44e933d8 is not valid; is your activity running?
05-20 15:12:53.602: ERROR/AndroidRuntime(696):at android.view.ViewRoot.setView(ViewRoot.java:505)
05-20 15:12:53.602: ERROR/AndroidRuntime(696):at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
05-20 15:12:53.602: ERROR/AndroidRuntime(696):at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
05-20 15:12:53.602: ERROR/AndroidRuntime(696):at android.view.Window$LocalWindowManager.addView(Window.java:424)

etc...

It has to do with passing the correct context to the array adapter I'm using for the spinner, but I feel like I've tried all possible options. This block is the culprit:

ArrayAdapter<String> adapter = new ArrayAdapter<String> (parent.getContext(), android.R.layout.simple_spinner_item, options); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); attrSpinner.setAdapter(adapter);

Here is the whole custom list adapter, so you can see where I'm using this block:

 public class ItemListAdapter extends BaseAdapter {
    public ItemListAdapter(Context context) {
        Context mContext = context;
    }

    public int getCount() {                 
        return attributes.length();
    }

    public Object getItem(int position) {
        return position;
    }

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

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

        LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View attr_item = li.inflate(R.layout.menu_attributes, null);

        TextView attrName = (TextView) attr_item.findViewById(R.id.attr_name);
        CheckBox attrCheck = (CheckBox) attr_item.findViewById(R.id.attr_checkbox);
        EditText attrText = (EditText) attr_item.findViewById(R.id.attr_edittext);
        Spinner  attrSpinner = (Spinner) attr_item.findViewById(R.id.attr_spinner);
        try {
            String attrID = attributes.getJSONObject(position).getString("AttrID");
            String type = attributes.getJSONObject(position).getString("Type");
            String itemLabel = attributes.getJSONObject(position).getString("ItemLabel");
            JSONArray values = attributes.getJSONObject(position).getJSONArray("Values");

            if (type.equals("select")) {
                attrCheck.setVisibility(View.GONE);
                attrText.setVisibility(View.GONE);

                ArrayList<String> options = new ArrayList<String>();
                for (int i=0;i<values.length();i++) {
                    options.add(values.getJSONObject(i).getString("Name"));
                    Log.i("value options", values.getJSONObject(i).getString("Name"));
                }

//HERE IS THE PROBLEM
                ArrayAdapter<String> adapter = new ArrayAdapter<String> (parent.getContext(), android.R.layout.simple_spinner_item, options);
                adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                attrSpinner.setAdapter(adapter);

            }
            else if (type.equals("checkbox")){
                attrSpinner.setVisibility(View.GONE);
                attrText.setVisibility(View.GONE);
            }
            else if (type.equals("textarea")){
                attrSpinner.setVisibility(View.GONE);
                attrCheck.setVisibility(View.GONE);
            }
            else if (type.equals("text")){
                attrSpinner.setVisibility(View.GONE);
                attrCheck.setVisibility(View.GONE);
            }

            attrName.setText(itemLabel);

        } catch (JSONException e) {
                // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return attr_item;
    }

Any help is greatly appreciated. Thanks.

Can you explain how are you using MenuAttributes and LocalActivityRecord ?

It is using the latter's Context ( android.app.LocalActivityManager$LocalActivityRecord@44e933d8 ), while probably you need to provide the MenuAttributes object's Context.

To simplify, I would have an upper level Context context; field in the MenuAttributes class (you can set it as this.context = this; in onCreate() ) and use that field as:

ArrayAdapter<String> adapter = new ArrayAdapter<String> (context, android.R.layout.simple_spinner_item, options); 

I couldn't get this to work, so I switched it to radio buttons. Then I ran into another issue with values disappearing from edittext fields when the list is scrolled.

After doing some research I found that putting form controls inside ListView is a very bad idea because it has many bugs in android. See this previous post: http://bit.ly/mhvL1D

I switched to a ScrollView with nested LinearLayouts containing the various form controls.

Magically, all my problems have gone away. The spinner now works great and the EditText no longer disappears on scroll.

I was just going about the whole process wrong.

Lesson Learned: Don't use ListView for form controls.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM