Android 为 Spinner 创建一个 setError()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3749971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating a setError() for the Spinner
提问by Sameer Segal
How do you create the setError()
(similar to that of a TextView/EditText
) function for a Spinner
? The following doesn't work:
您如何setError()
为 a创建(类似于 a 的TextView/EditText
)函数Spinner
?以下不起作用:
I tried extending the Spinner class and in the constructor:
我尝试扩展 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
method:
setError
方法:
public void setError(String str) {
if (tv != null)
tv.setError(str);
if(tv2!=null)
tv2.setError(str);
if (ctv != null)
ctv.setError(str);
}
回答by EdmundYeung99
Similar to @Gábor's solution, but I didn't need to create my own adapter. I just call the following code in my validate function (i.e. on submit button clicked)
类似于@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
回答by Gábor
I have a solution that doesn't involve creating an extra edit field but you need your own SpinnerAdapter
, as usual.
我有一个解决方案,它不涉及创建额外的编辑字段,但SpinnerAdapter
像往常一样,您需要自己的.
Make sure you have at least one TextView
in the layout you use in your adapter's getView()
(you normally have that, anyway).
确保您TextView
在适配器中使用的布局中至少有一个getView()
(无论如何,您通常都有)。
Add the following function to your adapter (change name
to the ID of your TextView
):
将以下函数添加到您的适配器(更改name
为您的 ID TextView
):
public void setError(View v, CharSequence s) {
TextView name = (TextView) v.findViewById(R.id.name);
name.setError(s);
}
Call the setError()
from your code this way:
以setError()
这种方式从您的代码中调用:
YourAdapter adapter = (YourAdapter)spinner.getAdapter();
View view = spinner.getSelectedView();
adapter.setError(view, getActivity().getString(R.string.error_message));
Basically, as with any other control, only that you call it on your adapter and you have to provide the view as well.
基本上,与任何其他控件一样,只需在适配器上调用它,并且还必须提供视图。
This will display the error icon on the spinner as it is the case with other controls.
这将在微调器上显示错误图标,就像其他控件一样。
回答by CJBS
Using a hidden TextView to get a pop-up message to appear
使用隐藏的 TextView 来显示弹出消息
This solution involves adding an additional hidden textbox just below the spinner just at the right position to allow the TextView's error dialog to show, whilst also using the TextView set on the spinner's layout XML to allow the red (!) icon to be displayed. So in effect, two textviews are used -- one for the icon, and another (hidden) one to allow the error dialog.
此解决方案包括在微调器下方的正确位置添加一个额外的隐藏文本框,以允许显示 TextView 的错误对话框,同时还使用微调器布局 XML 上设置的 TextView 以允许显示红色 (!) 图标。所以实际上,使用了两个文本视图——一个用于图标,另一个(隐藏)用于允许错误对话框。
This is what it looks like when not in an error state (use SetError(null)
):
这是不处于错误状态时的样子(使用SetError(null)
):
This is what it looks like when there is an error (use SetError("my error text, ideally from a resource!")
):
这是出现错误时的样子(使用SetError("my error text, ideally from a resource!")
):
Here is the excerpt of the spinner's layout XML. There is a RelativeLayout used to ensure that the TextView is as close as possible to the spinner, and has just enough paddingRight to ensure that the arrow on the message dialog is aligned just under the red error (!) icon. The hidden (fake) TextView is positioned relative to the Spinner.
这是微调器布局 XML 的摘录。有一个 RelativeLayout 用于确保 TextView 尽可能靠近微调器,并且有足够的 paddingRight 以确保消息对话框上的箭头正好在红色错误 (!) 图标下方对齐。隐藏的(假的)TextView 是相对于 Spinner 定位的。
<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>
Note: @drawable/selector_listview
defined outside the scope of this solution. See example hereof how to get this to work, as it's off topic for this answer.
注意:@drawable/selector_listview
在本解决方案范围之外定义。请参阅此处的示例,了解如何使其工作,因为它与此答案无关。
Here is the code to make it work. Just call the SetError(errMsg)
either with null
to clear the error, or with text to set it in an error state.
这是使其工作的代码。只需调用SetError(errMsg)
withnull
清除错误,或调用text 将其设置为错误状态。
/**
* 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);
}
}
In the SetError
function above, example there is some additional code that causes the text in the Spinner to shake when the error is set. This is not required to make the solution work, but is a nice addition. See herefor the inspiration for this approach.
在SetError
上面的函数示例中,有一些额外的代码会在设置错误时导致 Spinner 中的文本抖动。这不是使解决方案起作用所必需的,但它是一个很好的补充。请参阅此处了解此方法的灵感。
Kudos to @Gábor for his solutionwhich makes use of the TextView on the Spinner's item layout XML. The code View view = spnMySpinner.getSelectedView();
(based on @Gábor's solution) is necessary, because it gets the currently displayed TextView, rather than using a findViewById
, which would just get the first TextView in the list (based on the Resource ID provided), and hence would not work (to display the red (!) icon) if very first item in the list is not selected.
感谢@Gábor的解决方案,该解决方案利用了 Spinner 项目布局 XML 上的 TextView。代码View view = spnMySpinner.getSelectedView();
(基于@Gábor 的解决方案)是必要的,因为它获取当前显示的 TextView,而不是使用 a findViewById
,它只会获取列表中的第一个 TextView(基于提供的资源 ID),因此不会工作(如果未选择列表中的第一项,则显示红色 (!) 图标)。
回答by Jarett Millard
This can be done without using a custom layout or adapter.
这可以在不使用自定义布局或适配器的情况下完成。
((TextView)spinner.getChildAt(0)).setError("Message");
The only downside to this approach is that the little popup with the error text will not show when the icon is tapped.
这种方法的唯一缺点是点击图标时不会显示带有错误文本的小弹出窗口。
回答by EladHackim
I would suggest you to put an empty EditText
right behind your spinner.
我建议你EditText
在你的微调器后面放一个空的。
On the xml set that EditText
在 xml 上设置 EditText
android:enabled="false"
android:inputType="none"
Now when you want to set an error to your spinner, simply set that error to the EditText
.
现在,当您想为微调器设置错误时,只需将该错误设置为EditText
.
Remember not to set that EditText
to invisibille
/ gone
. It won't work that way.
请记住不要将其设置EditText
为invisibille
/ gone
。它不会那样工作。
Also, note that by this method you can decide exactly where you want your error to appear.
另外,请注意,通过这种方法,您可以确定您希望错误出现的确切位置。
回答by Kwex
Thanks Gabor for your fantastic solution. In furtherance to your point, my solution is thus:
感谢 Gabor 的出色解决方案。为了进一步说明您的观点,我的解决方案是:
Custom Adapter
定制适配器
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);
}
}
}
Use adapter for Spinner
为 Spinner 使用适配器
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
}
});
Check for validation
检查验证
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;
}
}
回答by Oussaki
Actually this is very is , you just need to have only one TextView
in your View and then get the selected View from your spinner using getSelectedView()
if the main View in your selected View is a TextView
then directly Cast your View to TextView
and setError
like this :
其实这是非常的,你只需要拥有一个只TextView
在您的视图,然后使用您的微调得到选择查看getSelectedView()
,如果您选择查看的主视图是TextView
那么直接投下你观TextView
和setError
这样的:
((TextView) jobCategory.getSelectedView()).setError("Field Required");
Else if The Textview isn't directly the MAIN View then you need to find it by ID and cast it again and setError
this way :
否则,如果 Textview 不是直接的主视图,那么您需要通过 ID 找到它并以setError
这种方式再次投射:
((TextView) jobCategory.getSelectedView().findViewById(R.id.firstName)).setError("Field Required");
回答by Yury
I guess that Spinner is not the right place to put this method. In case of Spinner you should select one value and to values in the Spinner should be filtered on the level of your adapter. Thus, a user can choose only those values that are in the Spinner.
我猜 Spinner 不是放置这种方法的正确位置。在 Spinner 的情况下,您应该选择一个值,并且应该在您的适配器级别过滤 Spinner 中的值。因此,用户只能选择微调器中的那些值。
回答by j00ris
You can create your own adapter (extends BaseAdapter implements SpinnerAdapter). That way, you can access the TextViews that are displayed in the spinner. (getView and createViewFromResource methods - example: ArrayAdapter) When you add an empty list item to allow the user to keep the field empty until it becomes mandatory (first item in the spinner), you can store it's TextView as a private member in the adapter. Then, when it comes time to call setError("...") from the Activity or Fragment, you can call it on the adapter who can pass it to the empty TextView.
您可以创建自己的适配器(扩展 BaseAdapter 实现 SpinnerAdapter)。这样,您就可以访问显示在微调器中的 TextView。(getView 和 createViewFromResource 方法 - 示例:ArrayAdapter)当您添加一个空列表项以允许用户将字段保持为空直到它成为必需项(微调器中的第一项)时,您可以将它的 TextView 作为私有成员存储在适配器中. 然后,当需要从 Activity 或 Fragment 调用 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");
}
}