2012年10月18日木曜日

Android ListPopupWindow で折り返し表示させる

ListPopupWindow の1行のレイアウトに android.R.layout.simple_list_item_1 を指定すると、TextView に表示する文字列が1行の幅より長い場合に折り返さずに切れてしまいます。



android.R.layout.simple_list_item_1
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!-- Copyright (C) 2006 The Android Open Source Project  
  3.   
  4.      Licensed under the Apache License, Version 2.0 (the "License");  
  5.      you may not use this file except in compliance with the License.  
  6.      You may obtain a copy of the License at  
  7.     
  8.           http://www.apache.org/licenses/LICENSE-2.0  
  9.     
  10.      Unless required by applicable law or agreed to in writing, software  
  11.      distributed under the License is distributed on an "AS IS" BASIS,  
  12.      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  13.      See the License for the specific language governing permissions and  
  14.      limitations under the License.  
  15. -->  
  16.   
  17. <TextView xmlns:android="http://schemas.android.com/apk/res/android"  
  18.     android:id="@android:id/text1"  
  19.     android:layout_width="match_parent"  
  20.     android:layout_height="wrap_content"  
  21.     android:textAppearance="?android:attr/textAppearanceListItemSmall"  
  22.     android:gravity="center_vertical"  
  23.     android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"  
  24.     android:paddingRight="?android:attr/listPreferredItemPaddingRight"  
  25.     android:minHeight="?android:attr/listPreferredItemHeightSmall"  
  26. />  


  1. protected void showListPopup(View anchor) {  
  2.   
  3.     ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,   
  4.             android.R.layout.simple_list_item_1,   
  5.             android.R.id.text1,  
  6.             new String[] {   
  7.                "test",   
  8.                "test2test2test2test2test2test2test2test2test2",   
  9.                "test3",   
  10.                "test4" });  
  11.   
  12.     ListPopupWindow popup = new ListPopupWindow(this);  
  13.     popup.setAdapter(adapter);  
  14.     popup.setAnchorView(anchor);  
  15.     popup.show();  
  16. }  


android.R.layout.simple_dropdown_item_1line.xml のように singleLine や ellipsize を指定しているならわかりますが、そうではないのにどうしてなのか調べてみました。

android.R.layout.simple_dropdown_item_1line
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--  
  3. /* //device/apps/common/assets/res/any/layout/simple_spinner_item.xml  
  4. **  
  5. ** Copyright 2008, The Android Open Source Project  
  6. **  
  7. ** Licensed under the Apache License, Version 2.0 (the "License");   
  8. ** you may not use this file except in compliance with the License.   
  9. ** You may obtain a copy of the License at   
  10. **  
  11. **     http://www.apache.org/licenses/LICENSE-2.0   
  12. **  
  13. ** Unless required by applicable law or agreed to in writing, software   
  14. ** distributed under the License is distributed on an "AS IS" BASIS,   
  15. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   
  16. ** See the License for the specific language governing permissions and   
  17. ** limitations under the License.  
  18. */  
  19. -->  
  20. <TextView xmlns:android="http://schemas.android.com/apk/res/android"   
  21.     android:id="@android:id/text1"  
  22.     style="?android:attr/dropDownItemStyle"  
  23.     android:textAppearance="?android:attr/textAppearanceLargePopupMenu"  
  24.     android:singleLine="true"  
  25.     android:layout_width="match_parent"  
  26.     android:layout_height="?android:attr/listPreferredItemHeight"  
  27.     android:ellipsize="marquee" />  


ListPopupWindow では、内部で持っている PopupWindow に ListView ではなく、ListView を継承した DropDownListView をセットしています。
この DropDownListView で次のように obtainView() を Override して、そこで1行の View が TextView だったら setHorizontallyScrolling(true) をセットしています。

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/widget/ListPopupWindow.java#1110
  1. 1110     private static class DropDownListView extends ListView {  
  2.   
  3. 1159         /** 
  4. 1160          * <p>Avoids jarring scrolling effect by ensuring that list elements 
  5. 1161          * made of a text view fit on a single line.</p> 
  6. 1162          * 
  7. 1163          * @param position the item index in the list to get a view for 
  8. 1164          * @return the view for the specified item 
  9. 1165          */  
  10. 1166         @Override  
  11. 1167         View obtainView(int position, boolean[] isScrap) {  
  12. 1168             View view = super.obtainView(position, isScrap);  
  13. 1169   
  14. 1170             if (view instanceof TextView) {  
  15. 1171                 ((TextView) view).setHorizontallyScrolling(true);  
  16. 1172             }  
  17. 1173   
  18. 1174             return view;  
  19. 1175         }  


コメントに書いてありますが、「TextView を1行に固定する事でスクロール時にガタガタ動いてしまう状態を避ける」ためだそうです。

setHorizontallyScrolilng() は TextView のメソッドです。TextView の setSingleLine() 内で呼ばれる applySingleLine() から呼ばれていることからもわかるように、文字を1行にするかどうかに関わるメソッドです。

1行の View が TextView のときだけ setHorizontallyScrolilng() を呼ぶようになっているので、次のようになんらかの ViewGroup に入れてしまえば複数行で表示されます。

R.layout.row
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="match_parent"  
  3.     android:layout_height="wrap_content"  
  4.     android:gravity="center_vertical"  
  5.     android:minHeight="?android:attr/listPreferredItemHeightSmall"  
  6.     android:orientation="vertical"  
  7.     android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"  
  8.     android:paddingRight="?android:attr/listPreferredItemPaddingRight" >  
  9.   
  10.     <TextView  
  11.         android:id="@android:id/text1"  
  12.         android:layout_width="match_parent"  
  13.         android:layout_height="wrap_content"  
  14.         android:textAppearance="?android:attr/textAppearanceListItemSmall" />  
  15.   
  16. </LinearLayout>  


  1. protected void showListPopup(View anchor) {  
  2.   
  3.     ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,   
  4.             R.layout.row,   
  5.             android.R.id.text1,  
  6.             new String[] {   
  7.                "test",   
  8.                "test2test2test2test2test2test2test2test2test2",   
  9.                "test3",   
  10.                "test4" });  
  11.   
  12.     ListPopupWindow popup = new ListPopupWindow(this);  
  13.     popup.setAdapter(adapter);  
  14.     popup.setAnchorView(anchor);  
  15.     popup.show();  
  16. }  








0 件のコメント:

コメントを投稿