web-dev-qa-db-ja.com

ボタンのクリック時にベクトル描画可能パスの色を変更する方法

新しいAndroidサポートの更新により、ベクタードロウアブルは後方互換性を取得します。さまざまなパスのベクター画像があります。ボタンのクリック時に、またはプログラムに基づいてパスの色を変更したい入力値。ベクトルパスの名前パラメーターにアクセスできますか?次に、色を変更します。

35
suku

これを使用して、ベクトルドロウアブルのパスの色を変更します

VectorChildFinder vector = new VectorChildFinder(this, R.drawable.my_vector, imageView);

VectorDrawableCompat.VFullPath path1 = vector.findPathByName("path1");
path1.setFillColor(Color.RED); 

ライブラリはこちら: https://github.com/devsideal/VectorChildFinder

16
Deven

ベクター全体の色は、setTintを使用して変更できます。

次のように、レイアウトファイルでImageViewを設定する必要があります。

_<ImageView
    Android:id="@+id/myImageView"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:tint="@color/my_Nice_color"
    Android:src="@drawable/ic_my_drawable"
    Android:scaleType="fitCenter" />
_

次に、画像の色を変更します。

_DrawableCompat.setTint(myImageView.getDrawable(), ContextCompat.getColor(context, R.color.another_Nice_color));
_

注:ベクトルDrawableが背景としてimageViewに設定されている場合、myImageView.getDrawable()はnullpointerexceptionを提供します。

51
Marco HC

このメソッドを使用して、下位APIの色を変更し、フラグメントのベクトル色を変更できます

int myVectorColor = ContextCompat.getColor(getActivity(), R.color.colorBlack);
                    myButton.getIcon().setColorFilter(myVectorColor, PorterDuff.Mode.SRC_IN);

getActivityの代わりに、MainActivity.thisを使用してアクティビティのベクターカラーを変更する必要があります

5
Arshdeep Singh

同じことを行う方法はいくつかありますが、これは[Vector Drawables[〜#〜] svg [〜#〜](ローカル/ネットワーク)の両方で機能します。

imageView.setColorFilter(ContextCompat.getColor(context, 
R.color.headPink), Android.graphics.PorterDuff.Mode.SRC_IN);

(R.color.headPinkを選択した色に変更します)

2
Moonis Abidi

反射を使用せずに、実行時に個々のパスの色を変更できますcan

VectorMasterは、ベクトルドロウアブルを動的に制御します。このライブラリを使用して、ベクトルDrawableのあらゆる側面を動的に制御できます(Javaインスタンスを介して)。

アプリのbuild.gradleに次の依存関係を追加するだけです

dependencies {
    compile 'com.sdsmdg.harjot:vectormaster:1.0.9'
}

あなたの場合、簡単な色の変更が必要です:

ベクトルの例:your_vector.xml

<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:width="24dp"
    Android:height="24dp"
    Android:viewportWidth="24.0"
    Android:viewportHeight="24.0">
<path
    Android:name="outline"
    Android:pathData="M20.84,4..."
    Android:strokeColor="#5D5D5D"
    Android:fillColor="#00000000"
    Android:strokeWidth="2"/>

[〜#〜] xml [〜#〜]

<com.sdsmdg.harjot.vectormaster.VectorMasterView
    Android:id="@+id/your_vector"
    Android:layout_width="150dp"
    Android:layout_height="150dp"
    app:vector_src="@drawable/your_drawable" />

Java

VectorMasterView heartVector = (VectorMasterView) 
findViewById(R.id.your_drawable);

// find the correct path using name
PathModel outline = heartVector.getPathModelByName("outline");

// set the stroke color
outline.setStrokeColor(Color.parseColor("#ED4337"));

// set the fill color (if fill color is not set or is TRANSPARENT, then no fill is drawn)
outline.setFillColor(Color.parseColor("#ED4337"));

From: https://github.com/harjot-oberai/VectorMaster 、MITでライセンスされています。

ベクターのドロウアブルを完全に制御できるようになりました。

2
JeRoll

この他の質問に関する私の答えを確認してください: https://stackoverflow.com/a/38418049/1335438

テーマを使用し、パスをパラメータ化して動的に設定できるようにすることで、これを管理する方法については素晴らしいアイデアです。

1
saiyancoder

ライブラリなしでこれを達成し、データバインディングとKotlinを組み合わせることができます。

ButtonBinding.kt

    @SuppressLint("PrivateResource")
    @BindingAdapter("drawable:start", "drawable:color", "button:isClicked", requireAll = false)
    @JvmStatic
    fun Button.setDrawableStartColor(@DrawableRes start: Int, @ColorRes color: Int, isClicked: Boolean) {
        this.apply btn@{
        context.apply ctx@{
            val drawable = ContextCompat
                    .getDrawable(this, start)
                    ?.apply {
                        if (isClicked) {
                            setColorFilter(
                                    ContextCompat.getColor(this@ctx, color),
                                    PorterDuff.Mode.SRC_ATOP)
                        }
                    }

            setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)
        }
        }
    }

setCompoundDrawablesWithIntrinsicBoundsまたはsetCompoundDrawables(を直接使用できますが、現在の組み込みバウンド、この記事をチェックしてください here

my_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        xmlns:app="http://schemas.Android.com/apk/res-auto"
        xmlns:drawable="http://schemas.Android.com/apk/res-auto">

    <data>

        <import type="your.package.R"/>

        <variable
            name="actionListener"
            type="your.package.mvvmV2.account.profile.ProfileActionListener"/>

        <variable
            name="profileResponse"
            type="your.package.data.model.ProfileResponse"/>

        <variable
            name="viewModel"
            type="your.package.mvvmV2.home.HomeViewModel"/>
    </data>
            <Button
                drawable:color="@{R.color.white}"
                drawable:start="@{R.drawable.ic_person_blue}"
                Android:id="@+id/buttonProfile"
</layout>

クリックリスナーのセットアップでは、次の操作も実行できます。

YourFragment.kt

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        mViewBinding = AccountFragmentV2Binding
                .inflate(inflater, container, false)
                .apply {
                    viewModel = mViewModel // also, assign the correct view model to your xml
                    actionListener = this@AccountFragment
                    setLifecycleOwner(this@AccountFragment) // don't forget this
                }

        return mViewBinding.root
    }

    override fun onProfileClicked(v: View) {
        mViewBinding.apply {
            mViewModel.let {
                // change and store the state, but don't forget to reset to default
                it.clickState[R.drawable.v2_ic_person_blue] = v.isPressed
            }
            executePendingBindings() // update ui directly, without delays
        }
    }

ViewModel.kt

val clickState = ObservableArrayMap<Int, Boolean>()

    init {
        clickState[R.drawable.ic_aktivitas_blue] = false
        clickState[R.drawable.ic_person_blue] = false
        clickState[R.drawable.ic_bookmark_blue] = false
    }

@ color /または@drawableを使用する代わりに、整数リソースでバインディングアダプタを定義します。 @アノテーションを使用する場合(例:drawable:start="@{@drawable/id}")XMLで。

このようにデータバインディングを変更する

fun Button.setDrawable(start: Drawable, color: Color) {
// do the conversion to int id, it will be a mess. that's why I stick to receive int id from resource instead
}

また、@ aminographyから this を設定することを忘れないでください

Android Vector Drawableを使用する際の重要なポイントAndroid vector Drawable 21以下で、次のコードをに追加します

アプリレベルのbuild.gradle:

Android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

アプリケーションクラス:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}

このおかげで ここに答える@ Varunが他の選択肢を説明した 、私の場合の元の答え ここに

0
mochadwi

この投稿で@Eyalが述べたように https://stackoverflow.com/a/32007436/4969047

実行時に個々のパスの色を変更することはできません。 VectorDrawableCompatのソースコードを見ると、内部要素を名前で公開する唯一の方法はgetTargetByNameで、これはinnerprivateVectorDrawableCompatStateの状態クラスVectorDrawableCompat

パッケージはプライベートであるため(デフォルト)-使用できません( reflection を使用しない限り)。

0
Shubhral