web-dev-qa-db-ja.com

Androidで選択、チェック、アクティブ化される状態の違いは何ですか?

これらの状態の違いを知りたいです。これを明確にするウェブページは見つかりませんでした。

101
Louis

CheckedとActivatedの違いは実際には非常に興味深いものです。 Googleのドキュメントでさえ謝罪です(下に強調を追加)。

...たとえば、単一または複数の選択が有効になっているリストビューでは、現在の選択セットのビューがアクティブになります。 (ええ、私たちはここの用語について深く申し訳ありません。)アクティブ化された状態は、それが設定されているビューの子に伝播されます。

だからここに違いがあります:

  1. ActivatedはHoneycombで導入されたため、それ以前は使用できません
  2. Activatedは、すべてのビューのプロパティになりました。メソッドsetActivated()およびisActivated()があります
  3. アクティブ化は、設定されているビューの子に伝播します
  4. Checkedは、Checkableインターフェイスを実装するビューを中心に展開します。メソッドsetChecked()、isChecked()、toggle()
  5. ListView(Honeycombの後)は、以下のようにORバージョンに応じてsetChecked()Android setActivated()を呼び出します(Androidソースコードから取得)。

    if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
        if (child instanceof Checkable) {
            ((Checkable) child).setChecked(mCheckStates.get(position));
        } else if (getContext().getApplicationInfo().targetSdkVersion
                >= Android.os.Build.VERSION_CODES.HONEYCOMB) {
            child.setActivated(mCheckStates.get(position));
        }
    }
    

    MCheckStates変数に注意してください。リスト内のどの位置がチェック/アクティブ化されているかを追跡します。これらは、たとえばgetCheckedItemPositions()を介してアクセスできます。 ListView.setItemChecked()を呼び出すと、上記が呼び出されることにも注意してください。言い換えれば、setItemActivated()と同等に呼び出すことができます。

  6. Honeycombより前は、リスト項目にstate_checkedを反映する回避策を実装する必要がありました。これは、ListViewがsetChecked()をレイアウトの最上位のビューでのみ呼び出す(およびレイアウトはチェック可能を実装しない)ためであり、ヘルプなしでは伝播しません。これらの回避策は次の形式でした。ルートレイアウトを拡張してCheckableを実装します。コンストラクターで、Checkableを実装するすべての子を再帰的に検索します。 setChecked()などが呼び出されると、それらのビューに呼び出しを渡します。これらのビューがstate_checkedの異なるドロウアブルを使用して状態リストドロウアブル(CheckBoxなど)を実装している場合、チェックされた状態がUIに反映されます。

  7. Honeycombの後に必要なすべてのリスト項目にニース背景を行うには、次のようにstate_activatedのドロアブルでドロアブルリストを持つ必要があります(もちろんsetItemChecked()を使用します):

    <item Android:state_pressed="true"
        Android:drawable="@drawable/list_item_bg_pressed"/>
    <item Android:state_activated="true"
        Android:drawable="@drawable/list_item_bg_activated"/>
    <item Android:drawable="@drawable/list_item_bg_normal"/>
    
  8. HoneyCombより前のリストアイテムに素敵な背景を作成するには、state_checkedに対して上記のような操作を行います。また、Checkableインターフェイスを実装するには、最上位ビューを拡張する必要があります。その中で、onCreateDrawableState()を実装し、状態が変化するたびにrefreshDrawableState()を呼び出すことで、実装する状態がtrueかfalseかをAndroidに伝える必要があります。

    <item Android:state_pressed="true"
        Android:drawable="@drawable/list_item_bg_pressed"/>
    <item Android:state_checked="true"
        Android:drawable="@drawable/list_item_bg_checked"/>
    <item Android:drawable="@drawable/list_item_bg_normal"/>
    

...また、相対レイアウトでstate_checkedと組み合わせてCheckableを実装するコードは次のようになります。

public class RelativeLayoutCheckable extends RelativeLayout implements Checkable {

    public RelativeLayoutCheckable(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public RelativeLayoutCheckable(Context context) {
        super(context);
    }

    private boolean mChecked = false;

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }
    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void setChecked(boolean checked) {
        mChecked = checked;
        refreshDrawableState();
    }

    private static final int[] mCheckedStateSet = {
        Android.R.attr.state_checked,
    };

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, mCheckedStateSet);
        }
        return drawableState;
    }    

    @Override
    public void toggle() {
        setChecked(!mChecked);
    }
}

以下に感謝します:

http://sriramramani.wordpress.com/2012/11/17/custom-states/

Stackoverflow: カスタムボタン状態を追加する方法

Stackoverflow: セレクターに応答するカスタムチェック可能ビュー

http://www.charlesharley.com/2012/programming/custom-drawable-states-in-Android/

http://developer.Android.com/guide/topics/resources/drawable-resource.html#StateList

http://blog.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

172
Martin Harvey

doc によると:

  • Android:state_selectedブール値。 「true」は、方向コントロールでナビゲートするときにオブジェクトが現在のユーザー選択であるときにこのアイテムを使用する必要がある場合(たとえば、Dパッドでリストをナビゲートするとき)。オブジェクトが選択されていないときにこのアイテムを使用する場合は「false」。選択状態は、フォーカス(Android:state_focused)が十分でない場合(リストビューにフォーカスがあり、その中のアイテムがDパッドで選択されている場合など)に使用されます。

  • Android:state_checkedBoolean。オブジェクトのチェック時にこのアイテムを使用する場合は「true」。 「false」は、オブジェクトがチェックされていないときに使用する必要がある場合。

  • Android:state_activatedブール値。 「true」オブジェクトを永続的な選択としてアクティブ化するときにこのアイテムを使用する必要がある場合(永続ナビゲーションビューで以前に選択したリストアイテムを「強調表示」するなど)。オブジェクトがアクティブ化されていないときに使用する必要がある場合は「false」。 APIレベル11で導入されました。

ドキュメントはかなり明確だと思うので、問題は何ですか?

18
AMerle

この問題の他の解決策は次のとおりです。 https://github.com/jiahaoliuliu/CustomizedListRow/blob/master/src/com/jiahaoliuliu/Android/customizedlistview/MainActivity.Java

メソッドsetOnItemClickListenerをオーバーライドし、コードのさまざまなケースをチェックしました。しかし、間違いなくマービンの解決策ははるかに優れています。

listView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position,
        long id) {
    CheckedTextView checkedTextView =
            (CheckedTextView)view.findViewById(R.id.checkedTextView);
    // Save the actual selected row data
    boolean checked = checkedTextView.isChecked();
    int choiceMode = listView.getChoiceMode();
    switch (choiceMode) {
    // Not choosing anything
    case (ListView.CHOICE_MODE_NONE):
        // Clear all selected data
        clearSelection();
        //printCheckedElements();
        break;
    // Single choice
    case (ListView.CHOICE_MODE_SINGLE):
        // Clear all the selected data
        // Revert the actual row data
        clearSelection();
        toggle(checked, checkedTextView, position);
        //printCheckedElements();
        break;
    // Multiple choice
    case (ListView.CHOICE_MODE_MULTIPLE):
    case (ListView.CHOICE_MODE_MULTIPLE_MODAL):
        // Revert the actual selected row data
        toggle(checked, checkedTextView, position);
        //printCheckedElements();
        break;
    }
    }
});
0
jiahao