Spinner
アイテムのテキストが長すぎて1行に収まらない場合、テキストは折り返されずに切り取られます。これはonlyAPIレベル> = 11の場合のみです。以下にスクリーンショットを示しますAndroid4.2.2(左)間違った動作とAndroid2.3.3(右)期待どおりに見える場所。
_Android:singleLine="false"
_は、ここでは単に無視されます。したがって、_Android:lines
_、_Android:minLines
_などのような他のすべての試みと同様に、TextView
はウィンドウ幅よりもはるかに広いようです。
他の人が同じ問題を抱えているのを見ましたが、誰も解決策を見つけることができませんでした。だから、これはシステムのバグですか? OSのバージョン間のこの矛盾は意図したものではないと思います。
比較的単純な解決策を示唆する回答がいくつかありました。
カスタムAdapter
を作成し、getView()
およびgetDropDownView()
をオーバーライドします。この時点ではまだ元の問題が残っているため、これは解決策ではありません。適切な行の折り返しを処理するためにレイアウトはどのように見える必要があるのでしょうか?
ドロップダウンビューのTextView
を親ViewGroup
にラップします。 _Android:layout_width="match_parent"
_では機能しません。親の幅が奇妙なことに無制限に見えるためです。
ドロップダウンビューに固定幅を与えます。これは、Spinner
が持つことができるさまざまな幅には適していません。
そしてもちろん、テキストのどこかに_\n
_ sを手動で挿入することは解決策ではありません。
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));
_
ホロテーマスピナーでは、デフォルトでドロップダウンモードが使用されます。そして、デフォルトスタイルをオーバーライドするすべての動きは、スピナーモードをダイアログモードに切り替えるだけで、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);
}
});
}
}
_
ここでのソリューションの組み合わせのみが私のために働いた(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);
ダイアログスタイルのスピナーに切り替えることで、この問題を解決しました。
<Spinner
...
Android:spinnerMode="dialog" />
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;
}
}
私が試したことから、Spinner
テーマを使用中にHolo
で複数行のドロップダウンアイテムを実現することはできません。
回避策は次のとおりです。
Spinner
を継承しないHolo
のスタイルを作成します。これにより、複数行のドロップダウンアイテムが有効になります。Holo
- themedのようにします。これにより、(閉じた状態と開いた状態が表示されます):
実装の詳細:
Holo
のSpinner
テーマから継承し、Spinner
ドロップダウン項目に複数の行を表示する方法は、設定してもドロップダウンアイテムのTextView
singleLine
属性をfalse
に追加し、カスタムレイアウトを提供します。私はHolo
スタイルを維持しようとしましたが、
Android:spinnerStyle
Android:spinnerItemStyle
Android:spinnerDropDownItemStyle
スタイル属性(これらの属性の使用例 here )が、複数行の結果を生成することができませんでした。
ただし、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
ではなくSpinner
のように見え、矢印も視覚的な手がかりもないSpinner
。代わりにspinnerStyle
parentを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
を親に使用しないでください。 これにより、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
フォルダーにこれらのドロアブルを含めます:
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
- themedではありませんが、ドロップダウン項目の複数行表示が本当に重要な場合、おそらく許容可能なトレードオフです。
この例では、マニフェストでAndroid:minSdkVersion
が14
に設定され、Android:targetSdkVersion
が17
に設定されました。
Holo
グラフィックとspinner_background_holo_light.xml
コードは、 HoloEverywhere Copyright(c)2012 Christophe Versieux、Sergey Shatunovからのものです。ライセンスの詳細については、リンク先のgithubプロジェクトを参照してください。
Androidにはバグがあると思います。これを試すことができます。テキストからスペースを削除して表示すると、正常に機能します。 textviewの長さが文字列の長さより小さい場合、スペースの後のすべての文字を無視します。回避策として、これを試すことができます:
サンプルコードを使用して、multiline_spinner_dropdown_item.xmlという名前のres/layoutフォルダーにファイルを追加します。
<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でsingleLine属性をfalseに設定してレイアウトを変更します。
私は同じ問題に直面しました。スピナーのドロップダウンリストに2行表示したいのですが、見つけたすべての解決策は、このような単純な問題を解決するのに不合理に思えます。 Spinnerソースコード を調査し、属性Android:singleLine = "false"でcustom .xmlを使用すると、
<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;
}
それが、リストの行ごとに1行の文字列のみが表示される理由です。実際にはスクロールしています。
このような問題を解決するには、ViewをTextViewのnot instanceにして、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);
このソリューションは、スピナーモード(MODE_DROPDOWNとMODE_DROPDOWN)の両方で機能します。
この答えを読んで: textviewキャストエラー:-Android.widget.LinearLayoutをAndroid.widget.TextViewにキャストできません そしてこのトピック、私はこの問題を解決できます:TextViewをラップするLinearLayoutが必要です(スピナーテキスト)テキストが画面から出ないようにするために、解決すべき問題がいくつかあります。最初に、レイアウトを作成します(私はそれを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);
LinearLayoutを追加し、TextViewを指定し、getDropDownViewをオーバーライドして、データセット内の指定した位置にデータを表示するビューを取得する必要があるため、ArrayAdapterにレイアウト名とTextView idを追加することを忘れないでください。これで、スピナーが新しいバージョンと古いバージョンでうまく動作していることがわかりますAndroidバージョン
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);
問題が解決したことを願っています。
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>
ArrayAdapter<?> specAdapter =
ArrayAdapter.createFromResource(
getActivity().getBaseContext(),
aa[position],
Android.R.layout.select_dialog_item);
specAdapter.setDropDownViewResource(Android.R.layout.select_dialog_item);
これと同じ問題があり、解決策を見つけました。
テキストを初期表示とドロップダウンビューでも折り返したいと思いました。
テキストは最初の表示で折り返されていたので、ドロップダウンの場合、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は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>
これで、テキストはスピナーのドロップダウンビュー内と、表示されているスピナー内にラップされます。
これを機能させるために私がやったことは次のとおりです。
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"/>