setError()
をどのように作成しますか(TextView/EditText
)Spinner
?の関数以下は機能しません:
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);
}
@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
追加の編集フィールドを作成しないソリューションがありますが、通常どおり、独自のSpinnerAdapter
が必要です。
アダプターのgetView()
で使用するレイアウトに少なくとも1つのTextView
があることを確認してください(通常はそれがあります)。
次の関数をアダプターに追加します(name
をTextView
の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));
_
基本的に、他のコントロールと同様に、アダプタで呼び出すだけで、ビューも提供する必要があります。
これは、他のコントロールの場合と同様に、スピナーにエラーアイコンを表示します。
このソリューションでは、スピナーのすぐ下にある隠れたテキストボックスを追加して、TextViewのエラーダイアログを表示できるようにします。また、スピナーのレイアウトXMLに設定されたTextViewを使用して、赤色(!)アイコンを表示します。そのため、実際には2つのテキストビューが使用されます。1つはアイコン用で、もう1つ(非表示)はエラーダイアログを許可します。
これは、エラー状態でない場合の外観です(SetError(null)
を使用):
これは、エラーが発生した場合の外観です(SetError("my error text, ideally from a resource!")
を使用):
以下は、スピナーのレイアウト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で)、したがって動作しません(赤色(!)アイコンを表示するため)。
これは、カスタムレイアウトまたはアダプターを使用せずに実行できます。
((TextView)spinner.getChildAt(0)).setError("Message");
このアプローチの唯一の欠点は、アイコンがタップされたときにエラーテキストを含む小さなポップアップが表示されないことです。
空のEditText
をスピナーのすぐ後ろに置くことをお勧めします。
XmlでEditText
を設定します
Android:enabled="false"
Android:inputType="none"
これで、スピナーにエラーを設定する場合は、そのエラーをEditText
に設定するだけです。
EditText
をinvisibille
/gone
に設定しないでください。そのようには動作しません。
また、この方法により、エラーを表示する場所を正確に決定できることに注意してください。
素晴らしいソリューションをありがとう。あなたのポイントを促進するために、私のソリューションはこうして:
カスタムアダプター
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;
}
}
Spinnerはこのメソッドを配置するのに適切な場所ではないと思います。 Spinnerの場合、1つの値を選択し、アダプターのレベルでSpinnerの値をフィルターする必要があります。したがって、ユーザーはスピナーにある値のみを選択できます。
実際、これは非常に重要です。ビューに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");
独自のアダプタを作成できます(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");
}
}