web-dev-qa-db-fra.com

Comment changer la couleur du tracé dessiné par le vecteur en cliquant

Avec la nouvelle mise à jour du support Android, les dessins vectoriels bénéficient d’une compatibilité descendante. J'ai une image vectorielle avec différents chemins. Je veux que la couleur des chemins change au clic d'un bouton ou par programme en fonction d'une valeur d'entrée. Est-il possible d'accéder au paramètre name du chemin vectoriel? Et puis changez la couleur.

30
suku

Utilisez ceci pour changer une couleur de chemin dans votre dessin vectoriel

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

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

La bibliothèque est ici: https://github.com/devsideal/VectorChildFinder

11
Deven

La couleur de tout le vecteur peut être modifiée à l'aide de setTint.

Vous devez configurer votre ImageView dans votre fichier de mise en page comme ceci:

<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" />

Puis pour changer la couleur de votre image:

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

Remarque: myImageView.getDrawable() donne nullpointerexception si le vecteur drawable est défini sur l'imageView en tant qu'arrière-plan.

45
Marco HC

Vous pouvez utiliser cette méthode pour changer la couleur dans une API inférieure et pour changer la couleur du vecteur dans un fragment.

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

à la place de getActivity, vous devez utiliser MainActivity.this pour changer de couleur de vecteur en activité

5
Arshdeep Singh

Il y a plusieurs façons de faire la même chose, mais cela fonctionne à la fois pour Vector Drawables etSVG(Local/Network).

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

(changez R.color.headPink avec la couleur de votre choix)

2
Moonis Abidi

Vous pouvez modifier la couleur de chaque chemin au moment de l'exécution, sans utiliser de réflexion.

VectorMaster introduit un contrôle dynamique sur les dessins vectoriels. Chaque aspect d'un vecteur pouvant être dessiné peut être contrôlé de manière dynamique (via des instances Java), à l'aide de cette bibliothèque.

Ajoutez simplement la dépendance suivante dans le build.gradle de votre application

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

Dans votre cas, vous avez besoin d'un simple changement de couleur:

Exemple de vecteur: votre_vecteur.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"));

De: https://github.com/harjot-oberai/VectorMaster , sous licence MIT.

Vous avez maintenant un contrôle total sur les dessins vectoriels.

2
JeRoll

Vérifiez ma réponse sur cette autre question: https://stackoverflow.com/a/38418049/1335438 .

C'est une excellente idée sur la façon de gérer cela en utilisant des thèmes et en paramétrant les chemins afin de pouvoir les définir de manière dynamique.

1
saiyancoder

Vous pouvez y parvenir sans bibliothèque et combiner la liaison de données avec 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)
        }
        }
    }

Vous pouvez directement utiliser setCompoundDrawablesWithIntrinsicBounds ou setCompoundDrawables ( mais vous devez définir le liaison intrinsèque actuelle, consultez cet article ici

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>

Pour l’écouteur de clic de configuration, vous pouvez également procéder comme suit:

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
    }

Définissez l'adaptateur de liaison avec une ressource entière au lieu d'utiliser @ color/ou @drawable . Si vous préférez utiliser @ annotation (par exemple: drawable:start="@{@drawable/id}") sur le XML.

Changer la liaison de données comme ceci

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
}

De plus, n'oubliez pas de configurer this de @aminography

Point important de l'utilisation de Android Vecteur pouvant être dessiné Lorsque vous utilisez un vecteur Android pouvant être dessiné et que vous souhaitez une compatibilité ascendante pour les API inférieures à 21, ajoutez ce qui suit codes pour

Au niveau de l'application build.gradle:

Android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

En classe d'application:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}

Merci à ceci réponse ici , @ Varun a expliqué ici toute autre alternative , la réponse originale pour mon cas ici

0
mochadwi

Comme indiqué par @Eyal dans cet article https://stackoverflow.com/a/32007436/4969047

Vous ne pouvez pas changer la couleur du chemin individuel à l'exécution . En regardant le code source de VectorDrawableCompat, la seule méthode permettant d'exposer l'élément interne par son nom est getTargetByName qui est présente dans la classe d'état inner privateVectorDrawableCompatState of VectorDrawableCompat.

Puisqu'il s'agit d'un paquetage privé (par défaut), vous ne pouvez pas l'utiliser (à moins que vous utilisiez reflection ).

0
Shubhral