8

バックグラウンド

セレクターを "src" としてサポートするために、次の ImageView を作成しました。

public class CheckableImageView extends ImageView implements Checkable {
    private boolean mChecked;

    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };

    public CheckableImageView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.com_app_CheckableImageView, 0, 0);
        setChecked(a.getBoolean(R.styleable.com_app_CheckableImageView_com_app_checked, false));
        a.recycle();
    }

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

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

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    public interface OnCheckStateListener {
        void onCheckStateChanged(boolean checked);
    }

    private OnCheckStateListener mOnCheckStateListener;

    public void setOnCheckStateListener(OnCheckStateListener onCheckStateListener) {
        mOnCheckStateListener = onCheckStateListener;
    }

    @Override
    public void setChecked(final boolean checked) {
        if (mChecked == checked)
            return;
        mChecked = checked;
        refreshDrawableState();
        if (mOnCheckStateListener != null) 
            mOnCheckStateListener.onCheckStateChanged(checked);
    }
}

問題

上記のコードは、状態ごとに描画可能なアイテムとして画像ファイルを持つ通常のセレクターで正常に動作します。

つまり、ベクター型ドローアブル (「srcCompat」を使用) ではまったく機能しません。代わりに、空のコンテンツが表示されます。

これが私が試したことです:

        <...CheckableImageView
         ...
            app:srcCompat="@drawable/selector"/>

そして、セレクター(たとえば)は次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item  android:state_checked="true" android:drawable="@drawable/test"/>
    <item  android:state_pressed="true" android:drawable="@drawable/test" />
    <item android:drawable="@drawable/test2" />
</selector>

ベクタードローアブルの例:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="48"
        android:viewportHeight="48">

    <path
        android:fillColor="#0000ff"
        android:strokeColor="#000000"
        android:pathData="M 0 0 H 48 V 48 H 0 V 0 Z" />

    <path
        android:fillColor="#ff0000"
        android:strokeColor="#000000"
        android:pathData="M14.769224,32.692291l5.707315,-17.692275l3.073244,17.479182l6.585245,-16.413424l2.634209,16.200186l-4.170761,-8.526356l-5.048693,7.247362l-5.268419,-8.100027l-3.51214,9.805351z" />
</vector>

質問

うまくいかないのはなぜですか?私がしたことの何が悪いのですか?どうすれば修正できますか?

4

3 に答える 3

15

どうやら、これはサポート ライブラリの動作のバグであり、文書化されていません。

私はそれについてバグレポートを投稿しようとしましたが、UserError文書化されていないか、何らかの警告が表示されていないにもかかわらず、Google はそれを としてマークしました:

意図したとおりに動作します。AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) をオンにしない限り、コンテナーではベクターはサポートされません。

https://code.google.com/p/android/issues/detail?id=210745

そのため、セレクターが表示されない場合、またはこのログでクラッシュを引き起こす場合:

原因: android.content.res.Resources$NotFoundException: ドローアブル リソース ID #0x7f02004f からのファイル res/drawable/selector.xml

vectorDrawableセレクター内での使用を避けるか、 vectorDrawables.useSupportLibrary=true 行の使用を避ける必要があります。

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) を使用できますが、 docs によると、これは障害がある可能性があり (主にメモリ/パフォーマンスの問題)、使用することはまったくお勧めしません:

古いプラットフォーム (< API 21) のベクター型ドローアブルを DrawableContainer リソース内で使用できるかどうかを設定します。

有効にすると、AppCompat はフレームワークからドローアブル インフレーションをインターセプトできます。これにより、DrawableContainer リソース内のベクター ドローアブルの暗黙的なインフレーションが可能になります。これらのドローアブルは、ImageView の android:src や TextView の android:drawableLeft などの場所で使用できます。

この機能を有効にすると、メモリ使用量の問題や構成インスタンスの更新の問題が発生する可能性があるため、この機能はデフォルトで無効になっています。構成を手動で更新する場合は、おそらくこれを有効にしたくないでしょう。あなたは警告されました。

これを無効にしても、setImageResource(int) と app:srcCompat 属性を介してベクター リソースを引き続き使用できます。また、メニュー リソースなど、AppCompapt がインフレートするあらゆるもので使用することもできます。

注意: これは、この呼び出しの後に作成されたアクティビティでのみ有効になります。

于 2016-06-24T20:46:32.717 に答える