Wenn der Text eines Spinner
Elements zu lang ist, um in eine einzelne Zeile zu passen, wird der Text nicht umbrochen, sondern abgeschnitten. Dies ist only der Fall für API-Level> = 11 . Hier sind Screenshots von Android 4.2.2 (links), die das falsche Verhalten und Android 2.3.3 (rechts) wo es wie erwartet aussieht.
Android:singleLine="false"
Wird hier einfach ignoriert. Also, wie alle anderen Versuche wie Android:lines
, Android:minLines
Usw. Das TextView
scheint irgendwie viel breiter als die Fensterbreite zu sein.
Ich sah andere Leute, die das gleiche Problem hatten, aber niemand konnte eine Lösung finden. Also, ist das ein Systemfehler? Ich denke nicht, dass diese Inkonsistenz zwischen den Betriebssystemversionen beabsichtigt sein kann.
Es gab einige Antworten, die relativ einfache Lösungen vorschlugen.
Schreiben eines benutzerdefinierten Adapter
und Überschreiben von getView()
sowie getDropDownView()
. Dies ist hier nicht die Lösung, da an dieser Stelle noch das ursprüngliche Problem besteht: Wie muss das Layout aussehen, um einen ordnungsgemäßen Zeilenumbruch zu gewährleisten?
Wickeln Sie das TextView
der Dropdown-Ansicht in ein übergeordnetes ViewGroup
. Funktioniert nicht mit Android:layout_width="match_parent"
, Da die Breite des übergeordneten Elements seltsamerweise unbegrenzt zu sein scheint.
Geben Sie der Dropdown-Ansicht eine feste Breite. Dies ist nicht geeignet für die unterschiedlichen Breiten, die Spinner
haben kann.
Und natürlich besteht keine Lösung darin, \n
Irgendwo manuell in den Text einzufügen.
UPDATE: Ich habe dies auch als Beispielprojekt auf GitHub : Download hochgeladen
/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" />
Setze Adapter
:
spinner.setAdapter(ArrayAdapter.createFromResource(this,
R.array.items,
R.layout.spinner_item));
In Holo Theme verwendet Spinner standardmäßig den Dropdown-Modus. Und alle Bewegungen mit überschreibenden Standardstilen gehen in den Dialogmodus über, in dem mehrzeiliger Text wie in API 11 erfolgreich umbrochen wird. Stattdessen können Sie Spinner mit new Spinner(context, Spinner.MODE_DIALOG)
oder in xml: Android:spinnerMode="dialog"
Erstellen. Das Problem wird jedoch nicht behoben, da es sich um einen Dialog und nicht um eine Dropdown-Liste handelt.
Ich habe eine andere Lösung für dieses Problem gefunden: Überschreibe die getDropDownView
-Methode in ArrayAdapter
und setze setSingleLine(false)
in die Post-Ansichtsmethode. Wenn die Ansicht vollständig erstellt wurde, wird der Text in die entsprechenden Zeilen umgebrochen.
@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;
}
PDATE:
Und hier ist eine andere Antwort.
Binden Sie die Listenansicht manuell in PopupWindow ein und zeigen Sie sie beim Klicken unter TextView an und verbergen Sie sie beim Klicken auf listItem.
Einfache Implementierung, nur um die Idee zu zeigen:
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);
}
});
}
}
Hier hat nur eine Kombination von Lösungen für mich funktioniert (getestet auf Android 5.1 auch):
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);
Ich habe dieses Problem gelöst, indem ich zu einem Spinner im Dialogstil gewechselt bin:
<Spinner
...
Android:spinnerMode="dialog" />
Durch Hinzufügen eines linearen Layouts um die Textansicht wird der Text korrekt umbrochen.
Layout (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;
}
}
Mehrzeilige Dropdown-Elemente für ein Spinner
zu erstellen, während ein Holo
-Design verwendet wird, ist meines Erachtens nicht möglich.
Eine Umgehungslösung besteht darin,
Spinner
, der nicht von Holo
erbt. Dadurch werden mehrzeilige Dropdown-Elemente aktiviert.Holo
entspricht.Dies erzeugt (zeigt geschlossene und offene Zustände):
Details zur Implementierung:
Es gibt keine Möglichkeit, von einem Holo
-Thema auf dem Spinner
zu erben und im Dropdown-Element Spinner
mehrere Zeilen anzuzeigen, selbst wenn wir das Dropdown-Menü festlegen. Das TextView
singleLine
Attribut des Elements auf false
setzen und ein benutzerdefiniertes Layout bereitstellen. Ich habe auch versucht, den Holo
-Stil beizubehalten, aber den zu ändern
Android:spinnerStyle
Android:spinnerItemStyle
Android:spinnerDropDownItemStyle
stile Attribute (Beispiel für die Verwendung dieser Attribute hier ), aber ich konnte kein mehrzeiliges Ergebnis erzielen.
Wenn wir jedoch den Stil für Spinner
überschreiben und spinnerStyle
nicht von Holo
erben:
<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>
dann unterstützt das Dropdown-Element das Anzeigen mehrerer Zeilen. Aber jetzt haben wir das Holo
Thema auf dem Spinner
verloren und der geschlossene Zustand sieht aus wie ein TextView
kein Spinner
ohne Pfeil oder visuellen Hinweis, es ist ein Spinner
. Wenn wir stattdessen spinnerStyle
parent auf parent="Android:style/Widget.Spinner
Setzen:
<style name="spinnerStyle" parent="Android:style/Widget.Spinner">
<item name="Android:clickable">true</item>
</style>
im geschlossenen Zustand Spinner
wird der Pfeil angezeigt, der jedoch wie das graue Prä-Holo Spinner
gestaltet ist, das in einer Holo
App nicht an der richtigen Stelle angezeigt wird.
Eine mögliche Lösung ist also:
spinnerStyle
und verwenden Sie Holo
nicht für übergeordnete Elemente. Dadurch wird mehrzeiliger Text in den DropDown-Elementen aktiviert.Spinner
Hintergrund so, dass er das Holo
Thema übernimmt.Hier ist ein Beispiel:
Erstellen Sie eine Basisaktivität:
@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));
}
Aktivitätslayout:
<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>
stile:
<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>
platziere spinner_background_holo_light in einem zeichnbaren Ordner:
<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>
und füge diese Drawables in deinen drawables-hdpi
Ordner ein:
spinner_default_holo_light.9.png
spinner_disabled_holo_light.9.png
spinner_focused_holo_light.9.png
spinner_pressed_holo_light.9.png
Dies führt zu einem Drehfeld mit Holo
geschlossenen Status und mehrzeiligen Elementen, wie in den obigen Screenshots gezeigt.
Die Dropdown-Elemente in diesem Beispiel sind nicht dem Thema Holo
zugeordnet, aber es ist möglicherweise ein akzeptabler Kompromiss, wenn die mehrzeilige Anzeige der Dropdown-Elemente wirklich wichtig ist.
In diesem Beispiel wurde Android:minSdkVersion
In Manifest auf 14
Und Android:targetSdkVersion
Auf 17
Gesetzt.
Holo
Grafiken und der Code spinner_background_holo_light.xml
Stammen von HoloEverywhere Copyright (c) 2012 Christophe Versieux, Sergey Shatunov. Weitere Informationen zu Lizenzen finden Sie unter Linked-to-Github-Projekt.
Ich denke, es gibt einen Fehler auf Android. Sie könnten das versuchen. Entfernen Sie die Leerzeichen aus dem Text und zeigen Sie ihn dann an, damit er gut funktioniert. Wenn die Länge der Textansicht <der der Zeichenfolge ist, werden alle Zeichen nach dem Leerzeichen ignoriert. Zum Umgehen könnten Sie Folgendes versuchen:
fügen Sie eine Datei im Ordner res/layout mit dem Namen multiline_spinner_dropdown_item.xml mit dem folgenden Beispielcode hinzu:
<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" />
und wenn Sie den Spinner erstellen, erstellen Sie ihn aus diesem Layout.
Etwas wie :
ArrayAdapter.createFromResource(this, items, R.layout.multiline_spinner_dropdown_item);
Kopieren Sie im Allgemeinen das Layout Android.R.layout.simple_spinner_dropdown_item in das Projekt und ändern Sie das Layout, indem Sie das Attribut singleLine in CheckedTextView auf false setzen.
Ich stand vor dem gleichen Problem. Ich möchte 2 Zeilen in der Dropdown-Liste der Spinner sehen, aber alle Lösungen, die ich gefunden habe, erscheinen mir unvernünftig, um ein so einfaches Problem zu lösen. Ich untersuche Spinner-Quellcode und fand heraus, ob wir benutzerdefinierte .xml mit dem Attribut Android verwenden: 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" />
und Standard ArrayAdapter, der dem Code folgt, der jedes Mal in ListPopupWindow ausgeführt wird
@Override
View More obtainView(int position, boolean[] isScrap) {
View view = super.obtainView(position, isScrap);
if (view instanceof TextView) {
((TextView) view).setHorizontallyScrolling(true);
}
return view;
}
und deshalb sehen wir nur eine Zeichenfolgezeile pro Listenzeile, es wird tatsächlich gescrollt.
Um dieses Problem zu lösen, sollte unsere Ansicht keine Instanz von TextView sein. Platzieren Sie Ihre TextView einfach in FrameLayout oder 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>
und
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.multiline_spinner_dropdown_item,R.id.multiline_spinner_text_view,
awasomeListValues);
Diese Lösung funktioniert in beiden Spinner-Modi: MODE_DROPDOWN und MODE_DROPDOWN. Hoffentlich hilft es Ihnen!
Beim Lesen dieser Antwort: Fehler beim Casting von Textansichten: - Android.widget.LinearLayout kann nicht in Android.widget.TextView umgewandelt werden In diesem Thema konnte das Problem gelöst werden: Wir benötigen ein LinearLayout, das TextView (The spinner) umschließt text), um zu vermeiden, dass der Text vom Bildschirm verschwindet, wir werden jedoch einige Probleme zu lösen haben. Erstellen Sie zunächst das Layout ( Ich habe es spinner_dd_item.xml genannt):
<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>
Im nächsten Schritt wird eine ArrayAdapter-Instanz erstellt, um sie auf den Drehfeldern festzulegen:
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);
Vergessen Sie nicht, den Layoutnamen und die TextView-ID im ArrayAdapter hinzuzufügen, da wir das LinearLayout hinzugefügt haben und die TextView angeben und getDropDownView überschreiben müssen, um die Ansicht zu erhalten, in der die Daten an der angegebenen Position im Datensatz angezeigt werden. Jetzt können wir sehen, wie der Spinner Nizza auf neueren und älteren Android Versionen arbeitet
ich habe gerade herausgefunden, dass Android für diesen Fall bereits einen Stil hat
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);
hoffe es hat dein problem gelöst.
Wickle einfach TextView
mit LinearLayout
um:
<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>
ArrayAdapter<?> specAdapter =
ArrayAdapter.createFromResource(
getActivity().getBaseContext(),
aa[position],
Android.R.layout.select_dialog_item);
specAdapter.setDropDownViewResource(Android.R.layout.select_dialog_item);
Ich hatte das gleiche Problem und fand eine Lösung.
Ich wollte, dass der Text sowohl in der Ausgangsanzeige als auch in der Dropdown-Ansicht umgebrochen wird.
Der Text wurde in der Anfangsanzeige umgebrochen, und für die Dropdown-Liste hatte ich eine andere Lösung gefunden, die die Verwendung einer benutzerdefinierten Ansicht eines linearen Layouts mit fester Breite, die eine Textansicht einschließt, empfahl. Dadurch wurde das Dropdown-Menü des Drehfelds ebenso wie das der ursprünglichen Auswahl korrekt angezeigt. Dies verursachte jedoch ein großes Problem bei älteren Geräten.
Die anfängliche Anzeige wurde nicht aktualisiert und der Text nahm ein gestapeltes Aussehen an, wenn ich versuchte, etwas anderes auszuwählen. und da es nach unten gestapelt ist, hat das Hinzufügen eines Hintergrunds nicht geholfen.
Wie sich herausstellt, verfügen Adapter über eine Methode namens setDropDownViewResource (), mit der Sie eine andere Ansicht für das Dropdown festlegen können, als in der ursprünglichen Auswahl des Drehfelds angezeigt wird.
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);
in diesem Beispiel ist das simple_list_item die Standardansicht, die von Android und my_simple_list_item = bereitgestellt wird
<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>
Der Text wird jetzt in der Dropdown-Ansicht des Drehfelds UND in der angezeigten Auswahl des Drehfelds umbrochen.
Folgendes habe ich getan, damit es funktioniert:
ArrayAdapter<KeyValue> adapter = new ArrayAdapter<>(getContext(), R.layout.simple_dropdown_item_multiline, R.id.nameTextView, choices);
Und das ist der Inhalt von "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"/>