web-dev-qa-db-ja.com

スピナーのsetError()を作成する

setError()をどのように作成しますか(TextView/EditTextSpinner?の関数以下は機能しません:

Spinnerクラスとコンストラクターを拡張してみました:

ArrayAdapter<String> aa = new ArrayAdapter<String>(getContext(),
                    Android.R.layout.simple_spinner_item, Android.R.id.text1,
                    items);
            aa.setDropDownViewResource(Android.R.layout.simple_spinner_dropdown_item);
            setAdapter(aa);
             tv = (TextView) findViewById(Android.R.id.text1);
            // types_layout_list_tv

            ctv = (CheckedTextView) aa.getDropDownView(1, null, null);
            tv2 = (TextView) aa.getView(1, null, null);

setErrorメソッド:

    public void setError(String str) {
        if (tv != null)
            tv.setError(str);
        if(tv2!=null)
            tv2.setError(str);
        if (ctv != null)
            ctv.setError(str);
    }
46
Sameer Segal

@Gáborのソリューションに似ていますが、独自のアダプターを作成する必要はありませんでした。検証関数で次のコードを呼び出すだけです(つまり、送信ボタンがクリックされたとき)

        TextView errorText = (TextView)mySpinner.getSelectedView();                  
        errorText.setError("anything here, just to add the icon");
        errorText.setTextColor(Color.RED);//just to highlight that this is an error
        errorText.setText("my actual error text");//changes the selected item text to this
41
EdmundYeung99

追加の編集フィールドを作成しないソリューションがありますが、通常どおり、独自のSpinnerAdapterが必要です。

アダプターのgetView()で使用するレイアウトに少なくとも1つのTextViewがあることを確認してください(通常はそれがあります)。

次の関数をアダプターに追加します(nameTextViewのIDに変更します)。

_public void setError(View v, CharSequence s) {
  TextView name = (TextView) v.findViewById(R.id.name);
  name.setError(s);
}
_

この方法でコードからsetError()を呼び出します。

_YourAdapter adapter = (YourAdapter)spinner.getAdapter();
View view = spinner.getSelectedView();
adapter.setError(view, getActivity().getString(R.string.error_message));
_

基本的に、他のコントロールと同様に、アダプタで呼び出すだけで、ビューも提供する必要があります。

これは、他のコントロールの場合と同様に、スピナーにエラーアイコンを表示します。

20
Gábor

非表示のTextViewを使用してポップアップメッセージを表示する

このソリューションでは、スピナーのすぐ下にある隠れたテキストボックスを追加して、TextViewのエラーダイアログを表示できるようにします。また、スピナーのレイアウトXMLに設定されたTextViewを使用して、赤色(!)アイコンを表示します。そのため、実際には2つのテキストビューが使用されます。1つはアイコン用で、もう1つ(非表示)はエラーダイアログを許可します。

これは、エラー状態でない場合の外観です(SetError(null)を使用):

Spinner in valid state

これは、エラーが発生した場合の外観です(SetError("my error text, ideally from a resource!")を使用):

Spinner in invalid state

以下は、スピナーのレイアウトXMLの抜粋です。 TextViewがスピナーにできるだけ近くなるようにするために使用されるRelativeLayoutがあり、メッセージダイアログの矢印が赤いエラー(!)アイコンのすぐ下に配置されるように十分なpaddingRightがあります。非表示の(偽の)TextViewは、スピナーを基準にして配置されます。

_    <RelativeLayout
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:gravity="top|left"
        >

        <Spinner
            Android:id="@+id/spnMySpinner"
            Android:layout_width="400dp"
            Android:layout_height="wrap_content"
            Android:layout_alignParentTop="true"
            Android:dropDownSelector="@drawable/selector_listview"
            Android:background="@Android:drawable/btn_dropdown"
            Android:paddingBottom="0dp"
            Android:layout_marginBottom="0dp"
            />

        <!-- Fake TextView to use to set in an error state to allow an error to be shown for the TextView -->
        <Android.widget.TextView
            Android:id="@+id/tvInvisibleError"
            Android:layout_width="0dp"
            Android:layout_height="0dp"
            Android:layout_alignRight="@+id/spnMySpinner"
            Android:layout_alignBottom="@+id/spnMySpinner"
            Android:layout_marginTop="0dp"
            Android:paddingTop="0dp"
            Android:paddingRight="50dp"
            Android:focusable="true"
            Android:focusableInTouchMode="true"
            />

    </RelativeLayout>
_

注:_@drawable/selector_listview_は、このソリューションの範囲外で定義されています。 こちらの例をご覧ください この回答のトピックから外れているため、これを機能させる方法について.

これが機能するコードです。 nullを使用してSetError(errMsg)を呼び出してエラーをクリアするか、テキストを使用してエラー状態に設定します。

_/**
 * When a <code>errorMessage</code> is specified, pops up an error window with the message
 * text, and creates an error icon in the secondary unit spinner. Error cleared through passing
 * in a null string.
 * @param errorMessage Error message to display, or null to clear.
 */
public void SetError(String errorMessage)
{
    View view = spnMySpinner.getSelectedView();

    // Set TextView in Secondary Unit spinner to be in error so that red (!) icon
    // appears, and then shake control if in error
    TextView tvListItem = (TextView)view;

    // Set fake TextView to be in error so that the error message appears
    TextView tvInvisibleError = (TextView)findViewById(R.id.tvInvisibleError);

    // Shake and set error if in error state, otherwise clear error
    if(errorMessage != null)
    {
        tvListItem.setError(errorMessage);
        tvListItem.requestFocus();

        // Shake the spinner to highlight that current selection 
        // is invalid -- SEE COMMENT BELOW
        Animation shake = AnimationUtils.loadAnimation(this, R.anim.shake);
        spnMySpinner.startAnimation(shake);

        tvInvisibleError.requestFocus();
        tvInvisibleError.setError(errorMessage);
    }
    else
    {
        tvListItem.setError(null);
        tvInvisibleError.setError(null);
    }
}
_

上記のSetError関数には、エラーが設定されたときにスピナーのテキストを揺さぶる追加のコードの例があります。これは、ソリューションを機能させるために必須ではありませんが、素晴らしい追加です。 こちらを参照 このアプローチのインスピレーションについて。

his solution の@Gáborに感謝します。これは、スピナーのアイテムレイアウトXMLでTextViewを使用します。リストの最初のTextViewを取得するだけのfindViewByIdを使用するのではなく、現在表示されているTextViewを取得するため、コードView view = spnMySpinner.getSelectedView();(@Gáborのソリューションに基づく)が必要です(リストの最初の項目が選択されていない場合、提供されたリソースIDで)、したがって動作しません(赤色(!)アイコンを表示するため)。

11
CJBS

これは、カスタムレイアウトまたはアダプターを使用せずに実行できます。

((TextView)spinner.getChildAt(0)).setError("Message");

このアプローチの唯一の欠点は、アイコンがタップされたときにエラーテキストを含む小さなポップアップが表示されないことです。

6
Jarett Millard

空のEditTextをスピナーのすぐ後ろに置くことをお勧めします。

XmlでEditTextを設定します

Android:enabled="false"
    Android:inputType="none"

これで、スピナーにエラーを設定する場合は、そのエラーをEditTextに設定するだけです。

EditTextinvisibille/goneに設定しないでください。そのようには動作しません。

また、この方法により、エラーを表示する場所を正確に決定できることに注意してください。

5
EladHackim

素晴らしいソリューションをありがとう。あなたのポイントを促進するために、私のソリューションはこうして:

カスタムアダプター

    public class RequiredSpinnerAdapter<T> extends ArrayAdapter<T> {
        public RequiredSpinnerAdapter(Context context, int textViewResourceId,
                                      Java.util.List<T> objects) {
            super(context, textViewResourceId, objects);
        }

        int textViewId = 0;

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = super.getView(position, convertView, parent);
            if (view instanceof TextView) {
                textViewId = view.getId();
            }
            return view;
        }

        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            View row = super.getView(position, convertView, parent);
            return (row);
        }

        public void setError(View v, CharSequence s) {
            if(textViewId != 0){
                TextView name = (TextView) v.findViewById(textViewId);
                name.setError(s);
            }
        }
    }

スピナー用アダプターを使用

ArrayAdapter<String> arrayAdapter = new RequiredSpinnerAdapter<String>(PropertyAdd.this, R.layout.checked, status_arr);
    marketstatus_spinner.setAdapter(arrayAdapter);
    marketstatus_spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                                   int arg2, long arg3) {

            // Put code here
        }

        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
           // Put code here
        }
    });

検証を確認する

private boolean checkValidation() {
    if(marketstatus_spinner.getSelectedItem().toString().equals("")){
        RequiredSpinnerAdapter adapter = (RequiredSpinnerAdapter)marketstatus_spinner.getAdapter();
        View view = marketstatus_spinner.getSelectedView();
        adapter.setError(view, "Please select a value");

        return false;
    }
}
1
Kwex

Spinnerはこのメソッドを配置するのに適切な場所ではないと思います。 Spinnerの場合、1つの値を選択し、アダプターのレベルでSpinnerの値をフィルターする必要があります。したがって、ユーザーはスピナーにある値のみを選択できます。

0
Yury

実際、これは非常に重要です。ビューにTextViewが1つだけあり、選択したビューのメインビューがTextViewである場合、getSelectedView()を使用してスピナーから選択したビューを取得するだけです。このようにTextViewおよびsetErrorに:

((TextView) jobCategory.getSelectedView()).setError("Field Required");

それ以外の場合、Textviewが直接MAINビューでない場合は、IDで検索し、この方法で再度setErrorをキャストする必要があります。

 ((TextView) jobCategory.getSelectedView().findViewById(R.id.firstName)).setError("Field Required");
0
Oussaki

独自のアダプタを作成できます(BaseAdapterを拡張してSpinnerAdapterを実装します)。これにより、スピナーに表示されているTextViewにアクセスできます。 (getViewおよびcreateViewFromResourceメソッド-例: ArrayAdapter )空のリストアイテムを追加して、フィールドが必須になるまで(スピナーの最初のアイテム)ユーザーがフィールドを空のままにできるようにすると、TextViewを保存できます。アダプタのプライベートメンバーとして。次に、アクティビティまたはフラグメントからsetError( "...")を呼び出すときが来たら、空のTextViewに渡すことができるアダプターで呼び出すことができます。

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    return createViewFromResource(position, convertView, parent, mTextViewId);
}

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) {
    View view;
    TextView text;

    if (convertView == null) {
        view = inflater.inflate(resource, parent, false);
    } else {
        view = convertView;
    }

    try {
        text = (TextView) view;
    } catch (ClassCastException e) {
        Log.e(TAG, "You must supply a resource ID for a TextView", e);
        throw new IllegalStateException("MyAdapter requires the resource ID to be a TextView", e);
    }

    MyItem i = getItem(position);
    String s = (null != i) ? i.toString() : "";
    text.setText(s);

    if ("".equals(s) && null == mEmptyText) {
        this.mEmptyText = text;
    }

    return view;
}

public void setError(String errorMessage) {
    if (null != mEmptyText) {
        mEmptyText.setError(errorMessage);
    } else {
        Log.d(TAG, "mEmptyText is null");
    }
}
0
j00ris