10

我正在尝试使用默认的空选定项创建一个微调器,但它显示微调器选择中的第一个项目。如果我将空值添加到我的字符串,这是微调器中的选择源,那么在打开微调器后会显示空行。我该怎么做?这是我正在使用的代码:

  String[] ch = {"Session1", "Session2", "Session3"};
  Spinner sp = (Spinner)findViewById(R.id.spinner1);
  TextView sess_name = findViewById(R.id.sessname);
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,ch);
  sp.setAdapter(adapter);

  adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

  sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener({
      @Override
      public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
          int index = arg0.getSelectedItemPosition();
          sess_name.setText(ch[index]);

          Toast.makeText(getBaseContext(), "You have selected item : " + ch[index], Toast.LENGTH_SHORT).show();
      }
4

5 回答 5

15

巴拉克的解决方案有问题。当您选择第一项时,Spinner 不会调用 OnItemSelectedListeneronItemSelected()并刷新空内容,因为之前的位置和选择位置都是 0。

首先在字符串数组的开头放置一个空字符串:

String[] test = {" ", "one", "two", "three"};

第二次构建适配器,不要修改getView(),修改getDropDownView()。将空视图的高度设置为 1px。

public class MyArrayAdapter extends ArrayAdapter<String> {

    private static final int ITEM_HEIGHT = ViewGroup.LayoutParams.WRAP_CONTENT;

    private int textViewResourceId;


    public MyArrayAdapter(Context context,
                          int textViewResourceId,
                          String[] objects) {
        super(context, textViewResourceId, objects);
        this.textViewResourceId = textViewResourceId;
    }

    @Override
    public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
        TextView textView;

        if (convertView == null) {
            textView = (TextView) LayoutInflater.from(getContext())
                   .inflate(textViewResourceId, parent, false);
        } else {
            textView = (TextView) convertView;
        }

        textView.setText(getItem(position));
        if (position == 0) {
            ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
            layoutParams.height = 1;
            textView.setLayoutParams(layoutParams);
        } else {
            ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
            layoutParams.height = ITEM_HEIGHT;
            textView.setLayoutParams(layoutParams);
        }

        return textView;
    }
}
于 2013-03-15T06:06:48.760 回答
6

我参加聚会有点晚了,但这是我为解决这个问题所做的。
如果用户取消选择初始项目,则微调器将保留初始空状态。一旦选择了初始项目,它就像“正常”一样
在 2.3.3+ 上工作,我没有在 2.2 及以下版本上测试过

首先,创建一个适配器类...

public class EmptyFirstItemAdapter extends ArrayAdapter<String>{
    //Track the removal of the empty item
    private boolean emptyRemoved = false;

    /** Adjust the constructor(s) to fit your purposes. */
    public EmptyFirstitemAdapter(Context context, List<String> objects) {
        super(context, android.R.layout.simple_spinner_item, objects);
        setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    }

    @Override
    public int getCount() {
        //Adjust the count based on the removal of the empty item
        if(emptyRemoved){
            return super.getCount();            
        }
        return super.getCount()-1;            
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        if(!emptyRemoved){
            // Remove the empty item the first time the dropdown is displayed.
            emptyRemoved = true;
            // Set to false to prevent auto-selecting the first item after removal.
            setNotifyOnChange(false);
            remove(getItem(0));
            // Set it back to true for future changes.
            setNotifyOnChange(true);
        }
        return super.getDropDownView(position, convertView, parent);
    }

    @Override
    public long getItemId(int position) {
        // Adjust the id after removal to keep the id's the same as pre-removal.
        if(emptyRemoved){
            return position +1;
        }
        return position;
    }

}

这是我在strings.xml中使用的字符串数组

<string-array name="my_items">
    <item></item>
    <item>Item 1</item>
    <item>Item 2</item>
</string-array>

接下来,将 OnItemSelectedListener 添加到您的 Spinner...

mSpinner = (Spinner) mRootView.findViewById(R.id.spinner);
String[] opts = getResources().getStringArray(R.array.my_items);
//DO NOT set the entries in XML OR use an array directly, the adapter will get an immutable List.
List<String> vals = new ArrayList<String>(Arrays.asList(opts));
final EmptyFirstitemAdapter adapter = new EmptyFirstitemAdapter(getActivity(), vals);
mSpinner.setAdapter(adapter);
mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    //Track that we have updated after removing the empty item
    private boolean mInitialized = false;
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        if(!mInitialized && position == 0 && id == 1){
            // User selected the 1st item after the 'empty' item was initially removed,
            // update the data set to compensate for the removed item.
            mInitialized = true;
            adapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // Nothing to do
    }
});

这可能不是一个“完美”的解决方案,但我希望它对某人有所帮助。

于 2013-08-30T16:42:17.633 回答
2

经过一番思考,我相信我已经想出了实现您目标的方法。它涉及创建自定义适配器并设置/维护标志以确定是否选择了微调器中的项目。使用此方法,您无需创建/使用错误数据(您的空字符串)。

基本上,适配器getView方法为关闭的微调器设置文本。因此,如果您覆盖它并在那里设置条件,您可以在启动时有一个空白字段,并且在您做出选择后,它会出现在关闭的微调框中。唯一需要记住的是,当您需要查看关闭的微调器中的值时,您需要设置标志。

我创建了一个小示例程序(下面的代码)。

请注意,我只添加了示例所需的单个构造函数。您可以实现所有标准的 ArrayAdapter 构造函数,也可以只实现您需要的那些。

SpinnerTest.java

public class SpinnerTestActivity extends Activity {
    private String[] planets = { "Mercury", "Venus", "Earth", "Mars",
            "Jupiter", "Saturn", "Uranus", "Neptune" };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        CustomAdapter adapter = new CustomAdapter(this,              // Use our custom adapter
                android.R.layout.simple_spinner_item, planets);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                    int pos, long id) {
                CustomAdapter.flag = true;                       // Set adapter flag that something
                has been chosen
            }
        });
    }
}

CustomAdapter.java

public class CustomAdapter extends ArrayAdapter {
    private Context context;
    private int textViewResourceId;
    private String[] objects;
    public static boolean flag = false;
    public CustomAdapter(Context context, int textViewResourceId,
            String[] objects) {
        super(context, textViewResourceId, objects);
        this.context = context;
        this.textViewResourceId = textViewResourceId;
        this.objects = objects;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null)
            convertView = View.inflate(context, textViewResourceId, null);
        if (flag != false) {
            TextView tv = (TextView) convertView;
            tv.setText(objects[position]);
        }
        return convertView;
    }
}
于 2012-07-14T13:47:08.453 回答
0

这是我使用的。它以通用方式正确处理空(空)选择。它适用于任何模型类 T,只要类 T 正确实现toString(),以显示微调器中显示的文本,并且equals(),以便可以通过引用而不是位置索引来选择项目。

package com.10xdev.android.components;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * A spinner where no selection is possible, and other enhancements.
 * requires model class to properly implement Object.equals, with semantic comparaison (such as id comparaison)
 * and a proper toString(), whose result will be displayed in the spinner
 *
 * @author tony.benbrahim
 */

public class EnhancedSpinner<T> extends Spinner {
    private final EnhanceArraySpinnerAdapter<T> spinnerAdapter;
    private final List<T> items = new ArrayList<>();
    private T selected = null;

    public EnhancedSpinner(final Context context, final AttributeSet attributeSet) {
        super(context, attributeSet);
        spinnerAdapter = new EnhanceArraySpinnerAdapter<>(context, items);
        setAdapter(spinnerAdapter);
    }

    /**
     * sets the items to be displayed
     *
     * @param items
     */
    public void setItems(final List<T> items) {
        this.items.clear();
        //very iffy, but works because of type erasure
        this.items.add((T) "");
        this.items.addAll(items);
        spinnerAdapter.notifyDataSetChanged();
        updateSelected();
    }

    /**
     * set the selected item. this may be called before or after setting items
     *
     * @param item the item to select, or null to clear the selection
     */
    public void setSelected(final T item) {
        this.selected = item;
        updateSelected();
    }

    /**
     * gets the selected item, or null if no item is selected
     *
     * @return
     */
    @Override
    public T getSelectedItem() {
        return getSelectedItemPosition() != 0 ? (T) super.getSelectedItem() : null;
    }

    /**
     * set the error message for the select
     *
     * @param errorMessage
     */
    public void setError(final String errorMessage) {
        final TextView errorText = (TextView) getSelectedView();
        errorText.setError("error");
        errorText.setTextColor(Color.RED);
        errorText.setText(errorMessage);
    }

    private void updateSelected() {
        if (selected == null) {
            setSelection(0);
        } else {
            for (int i = 1; i < items.size(); ++i) {
                if (selected.equals(items.get(i))) {
                    setSelection(i);
                    break;
                }
            }
        }
    }

    private class EnhanceArraySpinnerAdapter<T> extends ArrayAdapter<T> {
        private final LayoutInflater inflater;

        public EnhanceArraySpinnerAdapter(final Context context, final List<T> objects) {
            super(context, android.R.layout.simple_spinner_item, objects);
            inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public View getDropDownView(final int position, final View convertView, final ViewGroup parent) {
            final TextView textView = convertView != null ? (TextView) convertView
                    : (TextView) inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
            final Object item = getItem(position);
            textView.setText(item.toString());
            final ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
            layoutParams.height = position == 0 ? 1 : LayoutParams.WRAP_CONTENT;
            textView.setLayoutParams(layoutParams);
            return textView;
        }
    }
}
于 2016-11-07T20:30:28.963 回答
-1

您必须将微调器的第一个元素放置为空,或者使用string指示未选择任何内容,如下所示:

String[] ch= {"","Session1", "Session2", "Session3"};

或者

String[] ch= {"Nothing selected", "Session1", "Session2", "Session3"};

希望有所帮助

于 2012-07-14T13:09:50.770 回答