If the text of a Spinner
item is too long to fit into a single line, the text is not wrapped but cut off. This is only the case for API level >= 11. Here are screenshots of Android 4.2.2 (left) which shows the wrong behavior and Android 2.3.3 (right) where it looks as expected.
android:singleLine="false"
simply gets ignored here. So as all other tries like android:lines
, android:minLines
, etc. The TextView
somehow seems to be much wider than the window width.
I saw other people having the same problem, but no one could find a solution. So, is this a system bug? I don't think this inconsistency between the OS versions can be intended.
There were some answers suggesting relatively simple solutions.
Writing a custom Adapter
and overriding getView()
as well as getDropDownView()
. This is not the solution here, because at this point, there is still the original problem: How does the layout have to look like to handle proper line wrapping?
Wrapping the TextView
of the drop down view into a parent ViewGroup
. Does not work with android:layout_width="match_parent"
because the width of the parent strangely seems to be unlimited.
Giving the drop down view a fixed width. This is not suitable with the different widths the Spinner
can have.
And of course, no solution is to manually insert \n
s anywhere into the text.
UPDATE: I also uploaded this as a sample project on GitHub: Download
/res/values/arrays.xml:
<string-array name="items"> <item>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.</item> <item>At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est.</item> </string-array>
/res/layout/spinner_item.xml:
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" style="?android:attr/spinnerDropDownItemStyle" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="none" android:minHeight="?android:attr/listPreferredItemHeight" android:singleLine="false" />
Set Adapter
:
spinner.setAdapter(ArrayAdapter.createFromResource(this, R.array.items, R.layout.spinner_item));
Spinners provide a quick way to select one value from a set. In the default state, a spinner shows its currently selected value. Touching the spinner displays a dropdown menu with all other available values, from which the user can select a new one. ListView is a view group that displays a list of scrollable items.
We can user onClickListner for spinner. Since spinner open when we click(tap) on it. And to chcek where the spinner is open or not we can use onItemSelectedListner callbacks. Tell me if you want further code example.
In holo theme spinner by default uses dropdown mode. And all moves with overriding default styles just move to switching spinner mode to dialog mode which succesfully wraps multiline text as in api 11. Instead you can create spinner with new Spinner(context, Spinner.MODE_DIALOG)
or in xml: android:spinnerMode="dialog"
. But it's not resolve the problem, because it's dialog, not dropdown.
I have found another solution for this trouble: Override getDropDownView
method in ArrayAdapter
and put setSingleLine(false)
in post method of view. So when view completely created it wraps the text to appropriate lines.
@Override public View getDropDownView(final int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = new TextView(_context); } TextView item = (TextView) convertView; item.setText("asddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"); final TextView finalItem = item; item.post(new Runnable() { @Override public void run() { finalItem.setSingleLine(false); } }); return item; }
UPDATE:
And here is another answer.
Manually wrap listview in PopupWindow and show it under TextView on click and hide it on listItem click.
Simple implementation just to show idea:
public class MySpinner extends TextView { private PopupWindow _p; private ListView _lv; public MySpinner(Context context) { super(context); init(); } public MySpinner(Context context, AttributeSet attributeSet){ super(context, attributeSet); init(); } private void init(){ setBackgroundResource(R.drawable.spinner_background); final List<String> list = new ArrayList<String>(); list.add("Very long text AAAAAAAAAAAAAAAA"); list.add("1 Very long text AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); list.add("2 Very long text A"); list.add("3 Very long text AAAAAAAAA"); setMinimumWidth(100); setMaxWidth(200); _lv = new ListView(getContext()); _lv.setAdapter(new ArrayAdapter<String>(getContext(), R.layout.simple_list_item_1, list)); _lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { _p.dismiss(); setText(list.get(i)); } }); setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { _p = new PopupWindow(getContext()); _p.setContentView(_lv); _p.setWidth(getWidth()); _p.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); _p.setTouchable(true); _p.setFocusable(true); _p.setOutsideTouchable(true); _p.showAsDropDown(view); } }); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With