微调不换行文字 - 这是一个Android的bug?(Spinner does not wrap t

2019-07-17 19:40发布

如果一个文本Spinner项是太长成单行线,文本不包装,而切断。 这是为了API级别> = 11的情况。 这里是安卓4.2.2(左),这显示了错误的行为和Android 2.3.3(右)在那里看起来如预期的截图。

android:singleLine="false"只是被这里被忽略。 所以其他所有尝试像android:linesandroid:minLinesTextView某种程度上似乎比窗口宽度宽得多。

我看到有同样的问题其他人,但没有人能找到一个解决方案。 所以,这是一个系统错误? 我不认为在操作系统版本之间的这一矛盾,可以预期的。


请注意:

有一些答案表明相对简单的解决方案。

  • 编写自定义Adapter和压倒一切的getView()以及getDropDownView() 这是不是这里的解决方案,因为在这一点上,仍然是原来的问题:如何布局必须像处理合适的换行?

  • 包裹TextView降下来查看到父ViewGroup 。 不工作android:layout_width="match_parent"因为父的宽度奇怪,似乎是无限的。

  • 给下拉查看一个固定的宽度。 这是不适合与不同宽度的Spinner可以有。

  • 当然,没有任何解决方法是手动插入\n随时随地S插入文本。


用下面的代码重现:

更新:我还上传了,这个是一个样本项目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));

Answer 1:

在默认情况下,全息主题微调使用下拉菜单模式。 而所有与压倒一切的默认样式移动刚刚转会切换微调模式对话框模式,成功地包装多行文本在API 11相反,你可以创建微调new Spinner(context, Spinner.MODE_DIALOG)或XML: android:spinnerMode="dialog" 。 但它不能解决问题,因为它是对话,而不是下拉列表。

我已经找到了这种麻烦另一种解决方案:覆盖getDropDownView方法ArrayAdapter和放setSingleLine(false)在视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;
}

更新:

这里是另一种答案。

手工包装列表视图中PopupWindow并显示它的TextView下的点击隐藏它的listItem点击。

简单的实现只是为了节目的想法:

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


Answer 2:

我已经通过切换到对话式的微调解决了这个问题:

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


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


Answer 4:

添加围绕TextView的一个的LinearLayout允许文本换行正确。

布局(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>

适配器:

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

}


Answer 5:

在实现多线下拉项Spinner ,而使用Holo主题是不可能的,从我已经试过。

一种解决方法的解决方案是:

  • 创建了一个样式Spinner不继承Holo 。 这将使多线下拉项。
  • “手动”风格的微调,所以它看起来像它的Holo为主题的。

这产生(表示关闭和打开状态):

执行的详细信息:

有没有办法从继承Holo的主题是Spinner ,并显示在多条线路Spinner下拉项目,据我所知,即使我们设置下拉项的TextView singleLine属性false和提供自定义布局。 我也试着保持Holo风格,但改变

android:spinnerStyle
android:spinnerItemStyle 
android:spinnerDropDownItemStyle 

样式属性(使用这些属性的例子在这里 ),但我不能让它产生一个多行的结果。

但是,如果我们覆盖的风格Spinner不继承spinnerStyleHolo

 <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不是Spinner ,没有箭头或视觉线索,这是一个Spinner 。 如果我们不是设置spinnerStyle家长: parent="android:style/Widget.Spinner

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

Spinner关闭状态会显示箭头,但会像样式灰色预全息Spinner ,看起来格格不入的Holo应用。

所以,一个可能的解决方案则是:

  • 覆盖为主题spinnerStyle ,不使用Holo父。 这将使在下拉列表中的项目多行文本。
  • 更改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文件夹:

spinner_default_holo_light.9.png

spinner_disabled_holo_light.9.png

spinner_focused_holo_light.9.png

spinner_pressed_holo_light.9.png

这产生用旋转器Holo为主题的闭合状态和多线项,如图屏幕截图的上方。

在这个例子中的下拉项目不是Holo为主题的,但也许是一个可以接受的折衷如果下拉列表项的多行显示是非常重要的。

在该示例中, android:minSdkVersion设定为14android:targetSdkVersion17中的清单。

Holo图形和spinner_background_holo_light.xml代码来自HoloEverywhere版权所有(C)2012克里斯托夫Versieux,谢尔盖Shatunov。 见链接到GitHub的项目许可证的详细信息。



Answer 6:

我面对同样的问题。 我希望看到2号线在旋转的下拉列表中,但我发现所有的解决方案在我看来不合理解决这样简单的问题。 我调查微调的源代码 ,我发现如果我们使用自定义.xml带属性的android:单线=“假”

<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的实例 ,只是把里面的FrameLayout或LinearLayout中你的TextView。

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

该解决方案可工作在两种模式下微调:MODE_DROPDOWN和MODE_DROPDOWN.Hope它可以帮助你!



Answer 7:

我认为这是一个错误在Android上。 你可以试试这个。 删除从文本的空间,然后显示它会正常工作。 如果的TextView的长度为<该字符串的,它忽略了空间之后的所有字符。 对于一个变通办法,你可以试试这个:

将文件添加到与样品代码multiline_spinner_dropdown_item.xml名为RES /布局文件夹:

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

当你正在创建的微调从这个布局创建它。

就像是 :

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

基本上,复制android.R.layout.simple_spinner_dropdown_item布局到项目,并通过在CheckedTextView设置单行属性设置为false修改布局。



Answer 8:

读这样的回答: TextView的铸造错误: - android.widget.LinearLayout不能转换为android.widget.TextView和这个话题,我可以解决这个问题:我们需要一个LinearLayout中包裹的TextView(旋转的文本),以避免文本得到出从屏幕,但是我们会有一些问题需要解决。 首先,创建布局( 我把它叫做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的ID上一个ArrayAdapter,因为我们添加了LinearLayout中,我们需要指定的TextView,并覆盖getDropDownView得到,在数据集中的指定位置显示的数据视图。 现在,我们可以看到在微调和新旧版Android版本的工作不错



Answer 9:

我刚刚发现它是Android有这种情况存在的风格

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

希望它能解决你的问题。



Answer 10:

我有这个同样的问题,找到了解决办法。

我想在初始显示,在下拉视图以及包裹的文本。

文本被包裹在初始显示和用于下拉我发现另一种解决方案推荐使用具有固定宽度包围一个TextView线性布局的自定义视图。 这使得微调外观的下拉正确,以及初始选择。 然而,这引起了旧设备上的一个重大问题。

初始显示不会刷新和文本发生在一个堆叠的样子,如果我想选择别的东西。 并且由于它向下堆叠添加背景并没有帮助。

事实证明适配器有一个方法叫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是由机器人和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> 

现在微调的下拉列表视图中,并在纺纱文字环绕显示的选择。



Answer 11:

只是包装TextViewLinearLayout

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


Answer 12:

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


Answer 13:

这里就是我所做的,使其工作:

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



Answer 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>

是这样的:

这是微调使用作为行布局:

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


文章来源: Spinner does not wrap text — is this an Android bug?