2012年2月23日木曜日

Android DrawableState でリストアイテムの背景を変える ViewGroup を作る

アイテムを選択可能なリスト用として、 CheckedTextView を使った

android.R.layout.simple_list_item_single_choice

<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeightSmall" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:gravity="center_vertical" android:checkMark="?android:attr/listChoiceIndicatorSingle" android:paddingLeft="?android:attr/listPreferredItemPaddingLeft" android:paddingRight="?android:attr/listPreferredItemPaddingRight" />



android.R.layout.simple_list_item_multiple_choice

<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:textAppearance="?android:attr/textAppearanceListItem" android:gravity="center_vertical" android:checkMark="?android:attr/listChoiceIndicatorMultiple" android:paddingLeft="8dip" android:paddingRight="8dip" />

が用意されていて

public class MainActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] data = { "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_single_choice, android.R.id.text1, data); setListAdapter(adapter); ListView lv = getListView(); lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE); } }

のように使うことで



のようにできます。


さて、

1行のレイアウトを複雑にしたい場合、内部に CheckBox を持ってその表示を変える方法に ついては Android Layout Cookbook に書きました。

CheckBox ではなく、単に1行の ViewGroup の背景色を変えて選択状態を変えたい場合は Checkable を implements した ViewGroup を作ります。

例えばリストの1行を LinearLayout にして、選択されたら背景を変えるようにするには、 このように LinearLayout を継承したクラスを作って Checkable を実装します。

CheckedLinearLayout.java public class CheckedLinearLayout extends LinearLayout implements Checkable { private boolean mChecked; private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; public CheckedLinearLayout(Context context) { this(context, null); } public CheckedLinearLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CheckedLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void toggle() { setChecked(!mChecked); } @Override public boolean isChecked() { return mChecked; } @Override public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; refreshDrawableState(); } } @Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; } }

Checkable インタフェースのメソッドは toggle(), isChecked(), setChecked() だけなのですが、 これを実装するだけでは背景は変わってくれません。
キモは onCreateDrawableState() で、ここで super.onCreateDrawableState() で LinearLayout の drawableState を取得し、それにチェック状態の state を mergeDrawableStates() で追加したものを返す必要があります。

MainActivity.java public class MainActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] data = { "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", "Data", }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, android.R.id.text1, data); setListAdapter(adapter); ListView lv = getListView(); lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE); } }

list_item.xml <?xml version="1.0" encoding="utf-8"?> <yanzm.example.drawablestatesample.CheckedLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_item_bg" android:gravity="center_vertical" android:orientation="vertical" android:padding="8dip" > <TextView android:id="@android:id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceListItem" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="sub text" android:textAppearance="?android:attr/textAppearanceListItemSmall" /> </yanzm.example.drawablestatesample.CheckedLinearLayout>

list_item.bg <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true"> <shape> <solid android:color="#666666" /> </shape></item> <item> <shape> <solid android:color="#00000000" /> </shape> </item> </selector>

こんな感じにタップした行の背景が変わるようになります。





0 件のコメント:

コメントを投稿