私は ListView を持っています。各項目には、bg 画像、textView、および 2 つの imageViews を持つカスタム LinearLayout があります。ここで、ユーザーがアイテムに触れている間、それらすべてが「押された」状態に切り替わる必要があります。
- LiearLayout の背景画像を別のものに置き換える必要があります
- TextView は textColor を変更する必要があります
- アイテム内の両方の ImageView を代替画像に切り替える必要があります
通常、そのようなことは内部にセレクターを持つ xml リソースを使用して行われます。たとえば、LinearLayout は内部にセレクターを持つドローアブルを背景に使用し、TextView はセレクターと色を textColor に持つドローアブルを使用し、ImageViews は内部に画像を含むセレクターを src に使用します。
問題は、押された状態が LinearLayout によってのみ検出され、子ビュー (?) では検出されないため、背景画像のみが変更されることです。
OnTouchListener を使用してこれを実装しようとしましたが、リスト項目内のビューに安全にアクセスできないという問題が発生します。
リスト項目の getView() で返すビューをキャッシュして、後で画像とテキストの色を変更しようとしました。これは通常は機能しますが、たとえば、リスト項目の 1 つが別のアクティビティを開くと、ビューが何らかの形で失われ、強調表示された状態が無期限に維持されます。デバッグを試みましたが、デバッガーでステップスルーすると正しく動作します。
また、 cachedView を再利用すると、まったく役に立たないようで、完全に台無しになるため、毎回リスト項目の新しいビューを膨らませるだけです (これは非効率的です)。
念のため、カスタム リスト アダプターに使用しているカスタム リスト アイテム item のコードを次に示します。
public class MyListItem extends AbstractListItem
{
private int iconResource, iconHighlightedResource;
private int textResource;
private View.OnClickListener onClickListener;
private LinearLayout currentView;
private ImageView imgIcon;
private TextView txtText;
private ImageView imgArrow;
private boolean bIsHighlighted;
public MyListItem(int iconResource, int iconHighlightedResource, int textResource, View.OnClickListener onClickListener)
{
this.iconResource = iconResource;
this.iconHighlightedResource = iconHighlightedResource;
this.textResource = textResource;
this.onClickListener = onClickListener;
}
public View getView(View cachedView)
{
this.currentView = buildView();
populateView();
update();
return this.currentView;
}
private LinearLayout buildView()
{
LayoutInflater inflater = (LayoutInflater)App.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return (LinearLayout)inflater.inflate(R.layout.my_menu_item, null);
}
private void populateView()
{
this.imgIcon = (ImageView)this.currentView.findViewById(R.id.img_menu_item_icon);
this.txtText = (TextView)this.currentView.findViewById(R.id.txt_menu_item_text);
this.txtText.setText(this.textResource);
this.txtText.setTypeface(App.fontCommon);
this.imgArrow = (ImageView)this.currentView.findViewById(R.id.img_menu_item_arrow);
this.currentView.setOnClickListener(this.onClickListener);
this.currentView.setOnTouchListener(this.highlighter);
}
private View.OnTouchListener highlighter = new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
int nAction = event.getAction();
int nActionCode = nAction & MotionEvent.ACTION_MASK;
switch (nActionCode)
{
case MotionEvent.ACTION_DOWN:
bIsHighlighted = true;
update();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
bIsHighlighted = false;
update();
break;
}
return false;
}
};
private void update()
{
if (this.bIsHighlighted)
{
updateForHighlightedState();
}
else
{
updateForNormalState();
}
}
private void updateForHighlightedState()
{
Resources r = App.get().getResources();
this.currentView.setBackgroundResource(R.drawable.button_beveled_m_call_to_action_taking_input);
this.imgIcon.setImageResource(this.iconHighlightedResource);
this.txtText.setTextColor(r.getColor(R.color.white));
this.imgArrow.setImageResource(R.drawable.arrow_highlighted);
}
private void updateForNormalState()
{
Resources r = App.get().getResources();
this.currentView.setBackgroundColor(r.getColor(R.color.white));
this.imgIcon.setImageResource(this.iconResource);
this.txtText.setTextColor(r.getColor(R.color.text_dark));
this.imgArrow.setImageResource(R.drawable.arrow);
}
}
レイアウト ファイル (xml) は次のとおりです。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/white"
android:gravity="center_vertical"
android:padding="5dp" >
<ImageView
android:id="@+id/img_menu_item_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/info" />
<TextView
android:id="@+id/txt_menu_item_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="24dp"
android:text="Menu item"
android:textColor="@color/text_dark"
android:layout_marginLeft="5dp" />
<ImageView
android:id="@+id/img_menu_item_arrow"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/arrow" />
</LinearLayout>