Spinner does not wrap text -- is this an Android bug?

Only a combination of solutions here worked for me (tested on Android 5.1 too) :

spinner_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="wrap_content">

  <TextView
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:singleLine="false"
    android:textAlignment="inherit"/>
</LinearLayout>

code

  final ArrayAdapter<String> spinnerArrayAdapter=new ArrayAdapter<String>(activity,R.layout.spinner_item,android.R.id.text1,spinnerItemsList)
  {
  @Override
  public View getDropDownView(final int position,final View convertView,final ViewGroup parent)
    {
    final View v=super.getDropDownView(position,convertView,parent);
    v.post(new Runnable()
    {
    @Override
    public void run()
      {
      ((TextView)v.findViewById(android.R.id.text1)).setSingleLine(false);
      }
    });
    return v;
    }
  };
  spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

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);
            }
        });
    }
}