Hatena::Groupandroid

Droidくん「JavaとXMLの魔境、Androidフレームワークの世界へようこそ!」

 | 

2010-06-30AndroidのGUIウィジェットをXMLで記述してカスタマイズする事例

画面全体を縦方向にスクロールできるようにする

19:18 | はてなブックマーク - 画面全体を縦方向にスクロールできるようにする - Droidくん「JavaとXMLの魔境、Androidフレームワークの世界へようこそ!」

Androidでビューをスクロールできるようにするためにはスクロールさせたい要素をScrollViewでかこむ。とチュートリアルなどではよく書いてある。

しかしScrollViewはレイアウトのルート要素になることはできないうえに、ScrollViewの直下に他のGUIウィジェットを直接配置することもできない。らしい。

単に適当に囲んだだけだと、ブラウザのiframeのように画面の一部のビューだけスクロールできるようになってしまったりしておかしい。



とくにどこにも書かれていないのだが、よくあるブラウザアプリなどのようにふつうに画面全体をスクロールさせるためには、

<LinearLayout><ScrollView><LinearLayout>あれこれ</LinearLayout></ScrollView></LinearLayout>とかしないといけないらしい。


ついでに念のためルート要素でandroid:scrollbarAlwaysDrawVerticalTrack="true"とかしておく。


res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
		
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:scrollbarAlwaysDrawVerticalTrack="true"
    android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">

	<ScrollView android:id="@+id/ScrollView01"
		android:layout_width="fill_parent" android:layout_height="fill_parent">
		
	    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	                  android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" >


               <!-- 画面全体の内容をここに記述 -->


		</LinearLayout>

	</ScrollView>
	
</LinearLayout>

Spinnerをカスタマイズする方法メモ

19:17 | はてなブックマーク - Spinnerをカスタマイズする方法メモ - Droidくん「JavaとXMLの魔境、Androidフレームワークの世界へようこそ!」

View側でなにも考えずにSpinnerというドロップダウン選択肢みたいなやつを作ると、

Webサイト上のチュートリアルでよく見るようなラジオボタンっぽい画像がついた文字の大きな選択肢になってくれない。

米粒のような小さいフォントで文字列が表示されてしまって押し難いことこのうえない。


スピナーはボタンを押す前のビューと押したあとに表示されるダイアログ風のビューのふたつがあって、それぞれ別々に指定する必要があるらしい。

ダイアログ風ビューのときの見た目は

adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);

のようにスピナーのArrayAdapterオブジェクトに対して明示的に指定しないと変えられないようだ。

これを忘れるとデフォルトの豆文字フォントで表示されてしまう。

レイアウトXMLで両方ともまとめて定義する方法はあるんだろうか…


android.R.layout.simple_dropdown_item_1lineはandroidフレームワーク内で定義済みのスタイルらしい。


res/layout/main.xml

<Spinner android:id="@+id/spn"
	android:prompt="選択肢を選んでください"
	android:layout_height="wrap_content" android:layout_width="wrap_content"
	android:layout_alignParentTop="true" android:layout_centerHorizontal="true"
	/>

src/com.example.hoge/Activity.java

Spinner spn = (Spinner) findViewById(R.id.spn);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity, R.layout.rowdata);
adapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
adapter.add("hoge");
spn.setAdapter(adapter)

SeekBarのツマミ(thumb)をカスタマイズする方法メモ

19:16 | はてなブックマーク - SeekBarのツマミ(thumb)をカスタマイズする方法メモ - Droidくん「JavaとXMLの魔境、Androidフレームワークの世界へようこそ!」

SeekBarというのはいわゆるスライダー(Slider)とも呼ばれている、横長のバーをぐりぐり動かして値を調整するようなUI

AndroidのデフォルトのSeekBarのツマミが小さすぎて操作しずらいと感じたため、カスタマイズしようとしたらものすごく面倒だった。

ググっていろいろと探したがMLや英語の質問サイトどころか公式ドキュメントにもろくな情報がない。

最終的に中国語のよくわからないブログなどを参考にしてなんとかカスタマイズできた。


res/layout/main.xml

<SeekBar android:id="@+id/HogeSeekbar"
	 style="@style/CustomSeekBar"
	 />

res/values/styles.xml

<style name="CustomSeekBar" parent="android:Widget.SeekBar">
	<item name="android:gravity">center_vertical</item>
	<item name="android:layout_width">300px</item>
	<item name="android:layout_height">wrap_content</item>
	<item name="android:paddingLeft">30px</item>
	<item name="android:paddingRight">10px</item>
	<item name="android:thumb">@drawable/thumb</item> <!-- ツマミに利用するdrawableを指定 -->
	<item name="android:max">5</item> <!-- 最大値。SeekBar全体がこの値で等分される -->
	<item name="android:progress">2</item> <!-- ツマミの初期位置 -->
</style>

SeekBarで値を調節するためのツマミのようなGUIパーツは、ユーザーからの入力によって複数の状態になるためそれぞれ指定する必要がある。

android:state_なんちゃらについては、XML内の順番とか複数のstateの組み合わせによっても挙動が変わるようで公式ドキュメントをいくら眺めてもなんの手がかりもない。。

Buttonウィジェットやリストウィジェットについてはそこそこ事例が多少あるのだがSeekBarのツマミの事例はほとんどなかった。

res/drawable/thumb.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
		
	<item
		android:state_focused="true"
		android:state_pressed="true"
		android:drawable="@drawable/thumb_focused"
		/>
		 
	<!-- ツマミにフォーカスの当たっていない標準の状態 -->
	<item
		android:state_focused="false"
		android:state_pressed="false"
		android:drawable="@drawable/thumb_shape"
		/>
		
	<item
		android:state_focused="true"
		android:state_pressed="false"
		android:drawable="@drawable/thumb_focused"
		/>
		 
	<item
		android:state_focused="true"
		android:drawable="@drawable/thumb_focused"
		/>
</selector>

実際にツマミとして表示されるdrawableのサンプル。

状態ごとに画像をたくさん用意しているチュートリアルはよくあるがここではshapeをxmlで指定する。

shapeについては画面全体やボタンなどのビューの背景をxmlで記述したshapeに指定するチュートリアルもよくあるが、サイズが変わる他の要素の背景ではなくそれ自体サイズをもつshapeを定義する必要がある。

<size android:width="30px" android:height="30px" />を記述しないと、サイズのある画像として認識されず、ビュー上で消えてしまうので注意が必要(背景に指定するときは勝手に引き伸ばしてくれるのでsize子要素はいらないのだが)。

thumb用xmlファイルはこれひとつではダメで実際はツマミの各状態にあわせて色を変えたりしてthumb_pressed.xml, thumb_focused.xml, ...etcをつくって指定する必要がある

res/drawable/thumb_shape.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
	<size android:width="30px" android:height="30px" />
	<solid android:color="#ffdcdcdc" />
    <corners android:radius="5px" />
    <padding android:left="10px" android:right="10px" android:top="10px" android:bottom="10px" />
</shape>

RadioButtonをカスタマイズする方法メモ

19:16 | はてなブックマーク - RadioButtonをカスタマイズする方法メモ - Droidくん「JavaとXMLの魔境、Androidフレームワークの世界へようこそ!」

ラジオボタンは複数の選択肢からひとつを選ぶためのUI

Spinner(ドロップダウン)との違いはすべての選択肢があらかじめ見える状態になっているか否かくらいか。


Androidの初期設定のRadioButtonウィジェットは驚くほど巨大でダサいので、これもカスタマイズしようとしたらいろいろハマった。

iPhoneではRadioButtonをフラットなボタンにしたようなUIがあるが、そういうやつはAndroidではないらしいのでつくった。


要点としては

RadioButtonをまとめる要素であるRadioGroupは標準では垂直に要素を並べるようになっているので水平に変更。

RadioButton要素は実際はボタンとテキストビューのふたつの部分から構成されている。

checkされているかを示している標準のボタンはでかくて邪魔なので消してしまう。

テキストビューの背景をボタンっぽいものに変更し、checkされているかどうかの状態によってこれを変えることで、あたかもたくさんのボタンウィジェットからひとつの選択肢を選べるようなFlatRadioButtonを実現する。


res/layout/main.xml

<RadioGroup android:id="@+id/rg_wb" android:orientation="horizontal"
		android:layout_width="fill_parent" android:layout_height="wrap_content">
		<RadioButton android:id="@+id/Option0" android:text="1"
			style="@style/FlatRadioButton" />
		<RadioButton android:id="@+id/Option1" android:text="2"
			style="@style/FlatRadioButton" />
		<RadioButton android:id="@+id/Option2" android:text="3"
			style="@style/FlatRadioButton" />
		<RadioButton android:id="@+id/Option3" android:text="4"
			style="@style/FlatRadioButton" />
		<RadioButton android:id="@+id/Option4" android:text="5"
			style="@style/FlatRadioButton" />
</RadioGroup>

res/values/styles.xml

<style name="FlatRadioButton" parent="android:Widget.CompoundButton.RadioButton">
	<item name="android:layout_height">wrap_content</item>
	<item name="android:layout_width">64px</item> <!-- ボタンの幅。画面の幅とボタンに表示するテキストと選択肢の数で調整する -->
	<item name="android:paddingTop">10px</item>
	<item name="android:paddingBottom">10px</item>
	<item name="android:paddingLeft">5px</item>
	<item name="android:paddingRight">4px</item>
	<item name="android:button">@null</item> <!-- ラジオボタンの先頭の画像を表示しないときにこれを指定するらしい。。。ひたすらググった結果判明 -->
	<item name="android:background">@drawable/flatbutton</item> <!-- ラジオボタンのテキストの背景部分をボタンぽいやつに指定。標準だと背景なし -->
	<item name="android:gravity">center_horizontal</item>
	<item name="android:textColor">#000000</item>
</style>

途中で面倒になったのでいくつかの状態でdrawableを使いまわしている。。

res/drawable/flatbutton.xml

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<!-- 選択状態の選択肢が押されたとき -->
	<item
		android:state_checked="true"
		android:state_pressed="true"
		android:drawable="@drawable/on_pressed"
		 />
	<!-- 選択されているとき -->
	<item
		android:state_checked="true"
		android:drawable="@drawable/on"
		 />
	<!-- 選択されていない選択肢が押されたとき -->
	<item
		android:state_checked="false"
		android:state_pressed="true"
		android:drawable="@drawable/off_pressed"
		 />
	<!-- 選択されていない選択肢にフォーカスがあたったとき -->
	<item
		android:state_focused="true"
		android:state_checked="false"
		android:state_pressed="false"
		android:drawable="@drawable/on"
		 />
	<!-- 選択されていない選択肢のデフォルト状態 -->
	<item
		android:state_checked="false"
		android:drawable="@drawable/off"
		/>
</selector>

状態のぶんだけボタンdrawable xmlをつくる

res/drawable/on.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke android:width="1px" android:color="#000000" />
        <gradient
        android:startColor="#ffcc00"
        android:endColor="#ff9933"
        android:angle="270" />
    <corners android:radius="3px" />
</shape>

AddyAddy 2012/02/15 05:05 Boom shakalaka boom boom, problem soelvd.

twhrwztwhrwz 2012/02/15 17:39 xvOg3K <a href="http://swmgvbwbpiyx.com/">swmgvbwbpiyx</a>

pbhhznpbhhzn 2012/02/17 21:25 iUnWbv <a href="http://maofsnogcxhv.com/">maofsnogcxhv</a>

JulianaJuliana 2013/11/22 18:21 Such an imrsipseve answer! You've beaten us all with that!

NelsonNelson 2013/11/24 08:53 Fidinng this post solves a problem for me. Thanks! http://ztmsjg.com [url=http://yhcxlfmx.com]yhcxlfmx[/url] [link=http://cjmuttefd.com]cjmuttefd[/link]

HanifHanif 2013/11/25 10:23 I really wish there were more <a href="http://kjhzglzeiph.com">artilces</a> like this on the web.

JohnJohn 2013/11/25 16:18 That's an inventive answer to an inenitstreg question http://puffhr.com [url=http://kujxpe.com]kujxpe[/url] [link=http://oragnrdre.com]oragnrdre[/link]

ゲスト



トラックバック - http://android.g.hatena.ne.jp/yuiseki/20100630
 |