web-dev-qa-db-ja.com

デフォルトで選択されたアイテムが空のスピナー

デフォルトの空の選択されたアイテムでスピナーを作成しようとしていますが、スピナーの選択肢から最初のアイテムが表示されます。スピナーの選択肢のソースである文字列にnull値を追加すると、スピナーを開いた後、その空の行が表示されます。どうすればいいですか?私が使用しているコードは次のとおりです。

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

Barakのソリューションには問題があります。最初のアイテムを選択すると、前の位置と選択位置の両方が0であるため、SpinnerはOnItemSelectedListenerのonItemSelected()を呼び出して、空のコンテンツを更新しません。

まず、文字列配列の先頭に空の文字列を配置します。

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

2番目のビルドアダプタ。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;
    }
}
_
14
Jiang Qi

私はパーティーに少し遅れていますが、これを解決するために私がしたことは次のとおりです。
ユーザーが最初のアイテムの選択をキャンセルした場合、スピナーは最初の空の状態を保持します。最初のアイテムが選択されると、「通常」として機能します
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
    }
});

それは「完璧な」解決策ではないかもしれませんが、誰かに役立つことを願っています。

6
Tom Bollwitt

少し考えてみて、あなたの目標を達成する方法を思いついたと思います。これには、カスタムアダプターの作成と、スピナーからのアイテムが選択されているかどうかを判別するためのフラグの設定/保守が含まれます。この方法を使用すると、偽のデータ(空の文字列)を作成/使用する必要はありません。

基本的に、adapter getViewメソッドは、閉じたスピナーのテキストを設定します。したがって、それをオーバーライドしてそこに条件を設定すると、起動時に空白のフィールドが表示され、選択を行った後、閉じたスピナーボックスに表示されます。唯一のことは、閉じたスピナーで値を確認する必要があるときはいつでも、フラグを設定することを忘れないでください。

小さなサンプルプログラムを作成しました(以下のコード)。

例に必要なコンストラクターを1つだけ追加したことに注意してください。すべての標準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;
    }
}
2
Barak

スピナーの最初の要素を空にするか、次のように何も選択されていないことを示すstringを付ける必要があります。

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

または

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

助けたい

0
Litus

これが私が使っているものです。 null(空)選択を一般的な方法で適切に処理します。クラスTがスピナーに表示されるテキストを表示するためのtoString()equals()を適切に実装している限り、任意のモデルクラスTで機能するため、項目は参照によって選択できます。位置インデックスよりも。

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;
        }
    }
}
0
Tony BenBrahim