Подтвердить что ты не робот

Spinner не обертывает текст - это ошибка Android?

Если текст элемента Spinner слишком длинный, чтобы вписаться в одну строку, текст не обернут, а обрезается. Это относится только к уровню API >= 11. Вот скриншоты Android 4.2.2 (слева), который показывает неправильное поведение и Android 2.3.3 (справа), где он выглядит так, как ожидалось.

Marym.pngxsXtn.png

android:singleLine="false" просто игнорируется здесь. Так как все остальные, например, android:lines, android:minLines и т.д. TextView как-то кажется намного шире ширины окна.

Я видел других людей, имеющих одну и ту же проблему, но никто не мог найти решение. Итак, это системная ошибка? Я не думаю, что это несоответствие между версиями ОС может быть предусмотрено.


Обратите внимание:

Были некоторые ответы, предлагающие относительно простые решения.

  • Написание пользовательского Adapter и переопределения getView(), а также getDropDownView(). Это не решение здесь, потому что на данный момент все еще существует оригинальная проблема: как макет должен выглядеть так, чтобы обрабатывать правильную упаковку строк?

  • Обтекание TextView раскрывающегося списка в родительском ViewGroup. Не работает с android:layout_width="match_parent", потому что ширина родителя странно кажется неограниченной.

  • Предоставление раскрывающегося списка фиксированной ширины. Это не подходит для разных ширин, которые может иметь Spinner.

  • И, конечно же, решение не должно вручную вставлять \n в любом месте текста.


Воспроизвести следующий код:

UPDATE: Я также добавил это как пример проекта GitHub: Загрузить

/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" />

Установить Adapter:

spinner.setAdapter(ArrayAdapter.createFromResource(this,
            R.array.items,
            R.layout.spinner_item));
4b9b3361

Ответ 1

В голой теме spinner по умолчанию использует выпадающий режим. И все движения с переопределяющими стилями по умолчанию просто переходят к переключению режима spinner в режим диалога, который успешно обертывает многострочный текст, как в api 11. Вместо этого вы можете создать spinner с помощью new Spinner(context, Spinner.MODE_DIALOG) или в xml: android:spinnerMode="dialog". Но это не решает проблему, потому что это диалог, а не раскрывающийся список.

Я нашел другое решение для этой проблемы: переопределите метод getDropDownView в ArrayAdapter и поместите setSingleLine(false) в метод post post. Поэтому, когда просмотр полностью создан, он переносит текст в соответствующие строки.

@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:

И вот еще один ответ.

Вручную переместите listview в PopupWindow и покажите его в TextView при щелчке и спрячьте его в списке.

Простая реализация, чтобы показать идею:

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

Ответ 2

Я решил эту проблему, переключившись на диалоговое окно:

<Spinner
  ...
android:spinnerMode="dialog" />

Ответ 3

Для меня работала только комбинация решений (тестирование на Android 5.1 тоже):

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>

код

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

Ответ 4

Достижение многострочных выпадающих элементов на Spinner при использовании темы Holo невозможно, из того, что я пробовал.

Обходным решением является:

  • создайте стиль для Spinner, который не наследуется от Holo. Это позволит создавать многострочные выпадающие элементы.
  • Стиль Spinner 'вручную', поэтому он выглядит как Holo -themed.

Это создает (показывает закрытые и открытые состояния):

enter image description here

Подробности реализации:

Нет способа наследовать от темы Holo на Spinner и показывать несколько строк в раскрывающемся элементе Spinner, насколько я могу судить, даже если мы установим раскрывающийся элемент TextView singleLine к false и поставьте собственный макет. Я также попытался сохранить стиль Holo, но изменив

android:spinnerStyle
android:spinnerItemStyle 
android:spinnerDropDownItemStyle 

атрибуты стилей (пример использования этих атрибутов здесь), но я не мог заставить его создавать многострочный результат.

Однако, если мы переопределим стиль для Spinner и не наследуем spinnerStyle от Holo:

 <style name="AppTheme" parent="android:Theme.Holo.Light">
    <item name="android:spinnerStyle">@style/spinnerStyle</item>
</style>

<--no parent attribute-->
 <style name="spinnerStyle">
    <item name="android:clickable">true</item>
</style>

то раскрывающийся элемент будет поддерживать показ нескольких строк. Но теперь мы потеряли тему Holo на Spinner, а закрытое состояние выглядит как TextView не a Spinner без стрелки или визуальной подсказки. Spinner. Если вместо spinnerStyle родительский элемент установить: parent="android:style/Widget.Spinner:

<style name="spinnerStyle" parent="android:style/Widget.Spinner">
    <item name="android:clickable">true</item>
</style>

закрытое состояние Spinner покажет стрелку, но будет выглядеть как серый pre-Holo Spinner, который выглядит неуместным в приложении Holo.

Итак, возможно решение:

  • Отмените тему для spinnerStyle и не используйте Holo для родителя. Это позволит многострочный текст в элементах DropDown.
  • Измените фон Spinner, чтобы он выглядел так, как наследует тему Holo.

Вот пример:

Создать базовую операцию:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Spinner spinner = (Spinner)findViewById(R.id.styled_spinner);

    spinner.setAdapter(ArrayAdapter.createFromResource(this,
            R.array.items,
            R.layout.spinner_item));        
}

Схема действий:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="50dip"
    tools:context=".MainActivity" >

    <Spinner
        android:id="@+id/styled_spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

стили:

<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="AppTheme" parent="android:Theme.Holo.Light">
        <item name="android:spinnerStyle">@style/spinnerStyle</item>
    </style>
    <style name="spinnerStyle">
        <item name="android:clickable">true</item>
        <item name="android:background">@drawable/spinner_background_holo_light</item>
    </style>
</resources>

в выделенной папке, поставьте spinner_background_holo_light:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_enabled="false"
        android:drawable="@drawable/spinner_disabled_holo_light" />
    <item android:state_pressed="true"
        android:drawable="@drawable/spinner_pressed_holo_light" />
    <item android:state_pressed="false" android:state_focused="true"
        android:drawable="@drawable/spinner_focused_holo_light" />
    <item android:drawable="@drawable/spinner_default_holo_light" />
</selector>

и включите эти чертежи в папку drawables-hdpi:

enter image description here spinner_default_holo_light.9.png

enter image description here spinner_disabled_holo_light.9.png

enter image description here spinner_focused_holo_light.9.png

enter image description here spinner_pressed_holo_light.9.png

Это создает счетчик с Holo -замкнутым закрытым состоянием и многострочными элементами, как показано на скриншотах выше.

Выпадающие элементы в этом примере не являются Holo -themed, но, возможно, это приемлемый компромисс, если многолинейное отображение выпадающих элементов действительно важно.

В этом примере в манифесте android:minSdkVersion было установлено значение 14 и android:targetSdkVersion - 17.

Holo и код spinner_background_holo_light.xml поступают из HoloEverywhere Авторское право (c) 2012 Кристоф Верси, Сергей Шатунов. См. Связанный с github проект для получения сведений о лицензии.

Ответ 5

Добавление LinearLayout вокруг TextView позволяет тексту переворачивать правильно.

Макет (common_domainreferencemodel_spinner_item.xml):

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

       <TextView
            android:id="@+id/nameTextView"
            android:singleLine="false"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

</LinearLayout>

Adapter:

public class DomainReferenceModelAdapter extends ArrayAdapter<DomainReferenceModel> {

    private List<DomainReferenceModel> objects;
    private LayoutInflater inflater;
    private int oddRowColor = Color.parseColor("#E7E3D1");
    private int evenRowColor = Color.parseColor("#F8F6E9");

    public DomainReferenceModelAdapter(Context context, int resource, List<DomainReferenceModel> objects) {
        super(context, resource, objects);
        this.objects = objects;
        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    static class ViewHolder {
        public TextView nameTextView;
    }

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

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        return getViewInternal(position, convertView, parent, true);
    }

    private View getViewInternal(int position, View convertView, ViewGroup parent, boolean isDropdownView) {
        View view = convertView;
        if (view == null) {
            view = inflater.inflate(R.layout.common_domainreferencemodel_spinner_item, null);
            ViewHolder viewHolder = new ViewHolder();
            viewHolder.nameTextView = (TextView) view.findViewById(R.id.nameTextView);
            view.setTag(viewHolder);
        }
        if (isDropdownView) {
            view.setBackgroundColor(position % 2 == 0 ? evenRowColor : oddRowColor);
        }
        ViewHolder holder = (ViewHolder) view.getTag();
        DomainReferenceModel model = objects.get(position);
        holder.nameTextView.setText(model.getName());
        return view;
    }

}

Ответ 6

Я думаю, что есть ошибка на Android. Вы можете попробовать это. Удалите пробелы из текста, а затем отобразите, что он будет работать нормально. Если длина текстового вида равна < это строка, она игнорирует все символы после пробела. Для обхода вы можете попробовать следующее:

добавить файл в папку res/layout с именем multiline_spinner_dropdown_item.xml с образцом кода:

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="false"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:ellipsize="marquee" />

и когда вы создаете spinner, создайте его из этого макета.

Что-то вроде:

ArrayAdapter.createFromResource(this, items, R.layout.multiline_spinner_dropdown_item);

В основном скопируйте макет android.R.layout.simple_spinner_dropdown_item в проект и измените макет, установив для атрибута singleLine значение false в CheckedTextView.

Ответ 7

Я столкнулся с той же проблемой. Я хочу видеть 2 строки в выпадающем списке spinner, но все найденные мной решения кажутся мне необоснованными для решения такой простой проблемы. Я исследую Исходный код Spinner, и я нашел, если мы используем пользовательский .xml с атрибутом android: singleLine = "false"

<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/multiline_spinner_text_view"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:singleLine="false" />

и по умолчанию ArrayAdapter, следующий код, выполняемый в ListPopupWindow каждый раз

    @Override
       View More obtainView(int position, boolean[] isScrap) {
            View view = super.obtainView(position, isScrap);

           if (view instanceof TextView) {
                ((TextView) view).setHorizontallyScrolling(true);
            }

            return view;        
}

и поэтому мы видим только одну строковую строку в строке списка, она фактически прокручивается.

Чтобы решить эту проблему, наше представление должно быть не экземпляром TextView, просто поместите свой TextView внутри FrameLayout или LinearLayout.

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

        <CheckedTextView
            android:id="@+id/multiline_spinner_text_view"
            android:layout_width="fill_parent"
            android:layout_height="?android:attr/listPreferredItemHeight"
            android:singleLine="false" />

    </LinearLayout>

и

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
               R.layout.multiline_spinner_dropdown_item,R.id.multiline_spinner_text_view,
                awasomeListValues);

Это решение работает в обоих режимах spinner: MODE_DROPDOWN и MODE_DROPDOWN. Надеюсь, это поможет вам!

Ответ 8

Считывание этого ответа: ошибка при отправке текста: - android.widget.LinearLayout не может быть добавлен в android.widget.TextView и этот раздел, я мог бы решить эту проблему: Нам нужно, чтобы LinearLayout обертывал TextView (текст Spinner), чтобы избежать выхода текста с экрана, но у нас возникнут проблемы для решения. Для начала создайте макет (я назвал его spinner_dd_item.xml):

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

        <TextView
            android:id="@+id/simple_spinner_dropdown"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="5dp"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:paddingTop="5dp"
            android:textColor="@color/colorAccent"
            tools:text="Hello" />
    </LinearLayout>

Следующий шаг - создать экземпляр ArrayAdapter, чтобы установить его на счетчик:

    ArrayAdapter<CharSequence> arrayAdapter = new ArrayAdapter<CharSequence>(getActivity(), R.layout.spinner_dd_item,
            R.id.simple_spinner_dropdown, hashmapToString(hashMap, keys)) {
        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return getView(position, convertView, parent);
        }
    };
    spinner.setAdapter(arrayAdapter);

Не забудьте добавить имя макета и идентификатор TextView в ArrayAdapter, потому что мы добавили LinearLayout, и нам нужно указать TextView и переопределить getDropDownView, чтобы получить представление, которое отображает данные в указанной позиции в наборе данных, Теперь мы видим, как spinner работает хорошо на более старых и старых версиях Android.

Ответ 9

У меня была такая же проблема и я нашел решение.

Я хотел, чтобы текст был завершен на начальном экране и в раскрывающемся меню.

Текст был обернут на начальном экране, а для раскрывающегося списка я нашел другое решение, рекомендующее использовать пользовательский вид линейного макета с фиксированной шириной, охватывающий текстовое представление. Это привело к тому, что выпадающий список был корректным, а также начальный выбор. Однако это вызвало серьезную проблему для старых устройств.

Начальный дисплей не обновляется, и текст берет на себя сложный вид, если я попытаюсь выбрать что-то еще. и поскольку он складывается вниз, добавление фона не помогло. enter image description here

Как оказалось, адаптеры имеют метод setDropDownViewResource(), который позволяет вам установить другое представление для раскрывающегося списка, чем то, что отображается в исходном выборе счетчика.

 import org.holoeverywhere.widget.Spinner;

 ArrayAdapter adapter1 = ArrayAdapter.createFromResource(this,R.array.array_of_strings,R.layout.simple_list_item_1);
 adapter1.setDropDownViewResource(R.layout.my_simple_list_item_1);
 spQ1.setAdapter(adapter1);

в этом примере simple_list_item - это представление по умолчанию, предоставленное android, а my_simple_list_item -

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

<TextView
  android:id="@+id/android:text1"
  android:layout_width="wrap_content"
  android:layout_height="50dp"
  android:ellipsize="marquee"
  android:layout_gravity="center_vertical"
  android:singleLine="false"/>

</LinearLayout> 

Теперь текст обертывается внутри раскрывающегося списка прядильщика И в выбранном прядильщике.

Ответ 10

Просто оберните TextView с помощью LinearLayout:

<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"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
</LinearLayout>

Ответ 11

ArrayAdapter<?> specAdapter =
   ArrayAdapter.createFromResource(
       getActivity().getBaseContext(),
       aa[position],
       android.R.layout.select_dialog_item);
specAdapter.setDropDownViewResource(android.R.layout.select_dialog_item);

Ответ 12

Вот что я сделал, чтобы заставить его работать:

ArrayAdapter<KeyValue> adapter = new ArrayAdapter<>(getContext(), R.layout.simple_dropdown_item_multiline, R.id.nameTextView, choices);

И это содержимое "simple_dropdown_item_multiline":

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content">

<TextView android:id="@+id/nameTextView"
          style="?android:attr/dropDownItemStyle"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:ellipsize="marquee"
          android:paddingBottom="@dimen/large"
          android:paddingTop="@dimen/large"
          android:singleLine="false"
          android:textAppearance="?android:attr/textAppearanceLargePopupMenu"/>

Ответ 13

я просто нашел, что у андроида есть существующий стиль для этого случая

final Spinner pelanggaran = (Spinner) findViewById(R.id.pelanggaran);
ArrayAdapter<CharSequence> pelanggaran_adapter = ArrayAdapter.createFromResource(this,R.array.pelanggaran_array, android.R.layout.simple_expandable_list_item_1);
pelanggaran_adapter.setDropDownViewResource(android.R.layout.simple_expandable_list_item_1);
pelanggaran.setAdapter(pelanggaran_adapter);

надеюсь, что он решил вашу проблему.

Ответ 14

Я решил эту проблему, добавив в текст \n (новую строку) (как это просто).

<string name="bmr1">sedentary (little or no exercise)</string>
<string name="bmr2">lightly active (light exercise/\nsports 1-3 days/week)</string>
<string name="bmr3">moderately active (moderate exercise/\nsports 3-5 days/week)</string>
<string name="bmr4">very active (hard exercise/\nsports 6-7 days a week)</string>
<string name="bmr5">extra active (very hard exercise/sports &amp;\nphysical job or 2x training)</string>

Похож:

введите описание изображения здесь

И это макет, который spinner использует как строку:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/default_listview_row"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:singleLine="false"
    android:gravity="center_vertical"
    android:textColor="@android:color/white"
    android:background="@android:color/transparent"
    android:padding="5dp" />