2

私は 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>
4

3 に答える 3

4

多くの実験の後、最終的にこれが機能しました。リスト項目レイアウト内のすべての子ビューにはandroid:duplicateParentState="true". 次に、それらすべてがセレクター ドローアブルを使用できます。コード内での余分な作業は必要ありません。

<?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="@drawable/my_item_bg"
    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/selector_info"
        android:duplicateParentState="true" />

    <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="@drawable/selector_color_my_button_text"
        android:layout_marginLeft="5dp"
        android:duplicateParentState="true" />

    <ImageView
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/selector_arrow"
        android:duplicateParentState="true" />

</LinearLayout>
于 2012-11-29T15:00:15.570 に答える
-1

リストビューにViewHolderパターンを追加することをお勧めします。これにより、リストビューの描画とUIの作成が最適化されます。

また、setTagを使用して行のインスタンスを保存することもできます。その中で、タッチイベントを処理できます。

于 2012-11-29T12:48:46.930 に答える
-1

カスタムの描画可能なセレクターを作成し、それらをリストビュー要素の背景として設定する必要があります。

ステップ1、プレス状態に適した背景色(指定したレイアウトファイルと同様ですが、線形の背景属性を別の色に設定)を使用して、別のレイアウト(この例ではlayout_selectedという名前)を作成します。

次に、ドローアブルセレクターを定義します。これは、ドローアブルフォルダーに配置されます)、どのインスタンスでどの背景を使用するかを定義します。これは次のようになります。

<!-- pressed -->
<item android:drawable="@drawable/layout_selected" android:state_pressed="true"/>
<!-- focused -->
<item android:drawable="@drawable/layout_normal" android:state_focused="true"/>
<!-- default -->
<item android:drawable="@drawable/layout_normal"/>

最後に、これをリストで使用するには、アダプターのレイアウトを設定するときに、標準のレイアウトではなく、作成したセレクターに設定します。

説明するのは少し難しいかもしれませんが、「ドローアブルセレクター」を使用して目的を達成したいと考えています。

于 2012-11-29T12:45:46.397 に答える