微调与空的默认选择项(Spinner with empty default selected ite

2019-06-26 07:37发布

我试图创建一个默认为空所选项目的微调,但它显示从纺丝器的选择的第一个项目。 如果我添加空值到我的字符串,它是在旋转的选择源,然后打开微调后的空行显示。 我应该怎么办呢? 这里的代码我使用:

  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();
      }

Answer 1:

巴拉克的解决方案有问题。 当您选择第一项,微调不会叫OnItemSelectedListener的onItemSelected()和刷新空的内容,因为以前的位置和选择位置都为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;
    }
}


Answer 2:

我有点迟到了,但这里是我做过什么来解决这个问题。
如果用户取消了选择初始项目的纺丝器将保留初始空状态。 一旦初始项目已选定它作为“正常”
工程于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到您的微调...

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
    }
});

它可能不是一个“完美”的解决方案,但我希望它可以帮助别人。



Answer 3:

经过一番思考,我相信我已经拿出来实现自己的目标的方法。 这包括创建自定义的适配器和设置/维护一个标志,以确定是否从旋转的项目已被选中。 使用这种方法,你不需要创建/使用虚假数据(你的空字符串)。

基本上,适配器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;
    }
}


Answer 4:

下面是我使用。 它正确处理了一般地空(空)的选择。 它适用于任何型号类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;
        }
    }
}


Answer 5:

你必须把微调的第一个元素为空,或者用string表示没有选定如下所示:

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

要么

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

希望能帮助



文章来源: Spinner with empty default selected item