読者です 読者をやめる 読者になる 読者になる

ListViewで1行で収まらない文字の表示試行

自メモ)

 これはあんま遣らない方法だと思われるけど
自分はまた使いそうなのでメモっておく

理想イメージ>

  • ランキング等のリストビュー1行表示で 凄い長い名前入れられる
    • => 全体が横スクロールする

でもうまく動かせなかったorz

出来たもの>

  • 対象の行のカラムのみスクロールする


通常は1行表示というと

<EditView
	android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
	android:imeOptions="actionSend|flagNoEnterAction"
	android:scrollHorizontally="true"
	android:maxLines="1"
	android:lines="1"
/>
	
<TextView
	android:scrollHorizontally="true"
	android:singleLine="true"
/>

の形で定義すればいいと思うけど、
TextViewの表示的には、画面外にはみ出る場合 自動的に


hogehoge....
のような表示になるので今一条件を満たしていない感じ・・

 要は名前等でせっかく長い名前つけたのに‥‥‥表示がいやん
となるわけですけど

  • 名前の文字数を8文字等に制限する
  • 画面自体を横スクロールする

で後者を頑張ろうという試み


・ 使う側のコードのスニペット

	ListView list = _findViewById(R.id.list);

	HogeAdapter adapter = new HogeAdapter(this);
	list.setAdapter(adapter);
	
	for(XXX){
		String line = "XX,XXX,XXX,XXX";
		adapter.add(line);
		adapter.notifyDataSetChanged();
	}



	@SuppressWarnings("unchecked")
	protected <T extends View> T _findViewById(final int id){
	    return (T)findViewById(id);
	}

実際はAsyncTask等で使うイメージなんでしょうけどね・・

	@Override
	protected Void doInBackground(Void... params) {
		//〜略〜
		String line = "XX,XXX,XXX,XXX";
		publishProgress(line);
		//〜略〜
	}

	@Override
	protected void onProgressUpdate(String... arr) {
		for (String s : arr) {
			adapter.add(beans_s);
			adapter.notifyDataSetChanged();
		}
	}

・カスタムArrayAdaptor

public class HogeAdapter extends ArrayAdapter<String> {

	private final int layoutId =R.layout.hoge_list;
	private LayoutInflater inflater;
	private List<String> items =new ArrayList<String>();
	
	final static int COLOR_ROW_ON = Color.rgb(55, 55, 55);
	final static int COLOR_ROW_FF = Color.rgb(125, 125, 125);

	
	public HogeAdapter(Context context) {
		super(context, layoutId);
		inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		items.clear();
	}

	public RankingArrayAdapter(Context context,String[] objects) {
		super(context, layoutId, objects);
		
		this.inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		
		items.clear();
		for(String s:objects){
			items.add(s);
		}
	}
	
	@Override
	public void add(String object) {
		super.add(object);
		items.add(object);
	}

    @Override
	public void insert(String object, int index) {
		super.insert(object, index);
		items.add(index, object);
	}

	static class ViewHolder {  
		TextView  numView;  
		ImageView iconView;  
		HorizontalScrollView nameViewP;
		TextView  nameView;
		ImageView optView;
	}  

	
	@Override
	public View getView(int position, View convertView,ViewGroup parent) {
		
		ViewHolder holder;
        	View rowView = convertView;
        	HorizontalScrollView nameViewP=null;
		TextView nameView =null;
		
		if (rowView == null) {
		rowView = inflater.inflate(layoutId, parent, false);

		LinearLayout ln = (LinearLayout)rowView;
 		numView= (TextView)ln.getChildAt(0);
		iconView= (ImageView)ln.getChildAt(1);
		nameViewP = (HorizontalScrollView)ln.getChildAt(2);
		nameView= (TextView)nameViewP.getChildAt(0);
		//nameView= (TextView)ln.getChildAt(2);
		optView= (ImageView)ln.getChildAt(3);

		holder = new ViewHolder();
			
 		holder.numView =numView;
		holder.iconView =iconView;
		holder.nameViewP = nameViewP;
		holder.nameView =nameView;
		holder.optView =optView;
    		rowView.setTag(holder);
        }
        else{
        	holder = (ViewHolder) rowView.getTag();
 		numView =holder.numView;
		iconView =holder.iconView;
 		nameViewP = holder.nameViewP;
		nameView =holder.nameView;
 		optView =holder.optView;
        }
		
		//[TODO] 1,-1,ほげほげ,-1 のデータを想定
		String[] data = items.get(position);
		numView.setText(data[0]);
		if(Integer.valueOf(data[1])==-1){
			//iconView.setImageBitmap(XXXX);
			iconView.setVisibility(View.VISIBLE);
		}
		else{
			iconView.setImageBitmap(null);
			iconView.setVisibility(View.GONE);
		}
		nameView.setText(data[2]);
		if(Integer.valueOf(data[3])==-1){
			//optView.setImageBitmap(XXXX);
			optView.setVisibility(View.VISIBLE);
		}
		else{
			optView.setImageBitmap(null);
			optView.setVisibility(View.GONE);
		}


		//行を列ごとにマダラ色に		
		if (position%2 ==0){
			numView.setBackgroundColor(COLOR_ROW_ON);
			iconView.setBackgroundColor(COLOR_ROW_ON);
			nameViewP.setBackgroundColor(COLOR_ROW_ON);
			nameView.setBackgroundColor(COLOR_ROW_ON);
			optView.setBackgroundColor(COLOR_ROW_ON);
		}
		else{
			numView.setBackgroundColor(COLOR_ROW_OFF);
			iconView.setBackgroundColor(COLOR_ROW_OFF);
			nameViewP.setBackgroundColor(COLOR_ROW_OFF);
			nameView.setBackgroundColor(COLOR_ROW_OFF);
			optView.setBackgroundColor(COLOR_ROW_OFF);
		}
		return rowView;
	}
}
  • Adaptorにinfrateされるレイアウト
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
>

<TextView
  android:textSize="@dimen/ListTxSize"
  android:lines="1"
  android:layout_width="0dip"
  android:layout_height="fill_parent"
  android:layout_weight="1"
  android:gravity="left"
/>


<ImageView
  android:layout_width="32dip"
  android:layout_height="32dip"
  android:layout_weight="0" 
  android:layout_gravity="left"
  android:gravity="left"
  android:scaleType="fitXY"
  android:visibility="gone"
/>


<!-- 
//変更前 ★
<TextView
  android:textSize="@dimen/ListTxSize"
  android:lines="1"
  android:layout_width="0dip"
  android:layout_height="fill_parent"
  android:layout_weight="2"
  android:layout_gravity="left"
  android:gravity="left"
  android:scrollHorizontally="true"
  android:ellipsize="end"/>
 -->
 
<!-- //変更後 ★ -->
<HorizontalScrollView 
  android:layout_width="0dip"
  android:fillViewport="true" 
  android:layout_height="fill_parent"
  android:layout_weight="2"
  android:layout_gravity="left"
>
	<TextView
	  android:layout_width="match_parent"
	  android:layout_height="match_parent"
	  android:textSize="@dimen/ListTxSize"
	  android:lines="1"
	  android:scrollHorizontally="true"
	  android:ellipsize="end"/>
</HorizontalScrollView>  
 

<ImageView
  android:layout_width="32dip"
  android:layout_height="32dip"
  android:layout_weight="0" 
  android:layout_gravity="right"
  android:gravity="right"
  android:scaleType="fitXY"
  android:visibility="gone"
/>

</LinearLayout>

・ListView のレイアウト

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:gravity="center_horizontal"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">
    	
	<TextView android:text="" android:id="@+id/TxTitle" 
	    android:layout_width="fill_parent" android:layout_height="10dip" />
	

<!-- 
//=> 本当はやりたかったこと★
<HorizontalScrollView 
	android:layout_below="@id/TxTitle"
	android:fillViewport="true" 
   	android:layout_width="fill_parent"
   	android:layout_height="fill_parent" 
   	android:layout_marginLeft="10dip"
	android:layout_marginRight="10dip"
	android:layout_marginTop="0dp"
	android:layout_marginBottom="130dip"
   	android:orientation="vertical">
	    
	<ListView android:id="@+id/list"
        	android:layout_width="match_parent"
        	android:layout_height="match_parent" 
	        android:minHeight="240dip"
	    	android:textSize="@dimen/ListTxSize"/>
</HorizontalScrollView>
 -->		
 

	<!-- ListViewを出来るだけ延ばす & 広告&ボタン分のマージンを開ける -->
<!-- //出来なかったので戻した処 ★ -->
	<ListView android:id="@+id/list"
		android:layout_below="@id/TxTitle"
		android:layout_marginLeft="10dip"
		android:layout_marginRight="10dip"
		android:layout_marginTop="0dp"
		android:layout_marginBottom="130dip"
	    	android:orientation="vertical"
        	android:layout_width="fill_parent"
        	android:layout_height="fill_parent" 
	        android:minHeight="240dip"
	    	android:textSize="@dimen/ListTxSize"
        	android:layout_gravity="right"/>
	

		<!-- 広告用フレームレイアウト -->
		<FrameLayout android:id="@+id/AdLayoutList" 
		    	android:layout_alignParentBottom="true"
	           	android:layout_centerHorizontal="true"
			android:foregroundGravity="center|bottom"
			android:layout_marginTop="5dip"
		    	android:layout_width="320dip" 
		    	android:layout_height="50dip"
		    	android:visibility="visible"/>
	
		<!-- 広告の上部に配置するボタンとか -->
		<LinearLayout 
			android:layout_above="@+id/AdLayoutList"
			android:layout_marginLeft="10dip"
			android:layout_marginRight="10dip"
			android:layout_marginTop="5dip"
			android:layout_marginBottom="0dip"
			android:orientation="horizontal" 
			android:gravity="center_horizontal"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content" 
		>
			<Button android:text="start"
	            		android:textColor="@color/white"
				android:textSize="@dimen/BtnRetListTxSize"
				android:textStyle="bold"
				android:layout_weight="1"
				android:id="@+id/BtnRetList"
				android:layout_width="0dip"
				android:layout_marginRight="8dip"
				android:layout_height="wrap_content" />
	
			<Button android:text="return"
	            		android:textColor="@color/white"
				android:textSize="@dimen/BtnRetListTxSize"
				android:textStyle="bold"
				android:layout_weight="1"
				android:id="@+id/BtnRetList"
				android:layout_width="0dip"
				android:layout_height="wrap_content" />
		</LinearLayout>
		
</RelativeLayout>

ちなみに殆どの人は知ってると思いますが

  • RelativeLayoutの中の
    • FrameLayout は


android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
あたりでしか制御が聞きません *1

 ちなみにそこら辺ちゃんとレイアウトで来てるかは
[Nexus7]のレイアウトでプレビューするといいでしょう


Ad広告を表示するときに

  • 「一番下の中央!」

というのがやたら見た目的に重視されますので知っとくと楽

あたりの話



TLから補足頂いたコメント)

自分なんかフォローして頂いて、コメント情報いただけるのは凄くありがたいです。
いつもありがとうございます(#よちよちこわい



追記)
ListViewに関しては

という話もあるみたいなので奥が深いな‥‥‥。

Androidが簡単とか言っている人たちの感覚がよくわかんない。。
収益性と技術的な難易度は全然別なんですよね。。

*1:gravity とか layout_gravity効かない