เปลี่ยนสีเติมในเนื้อหาเวกเตอร์ใน Android Studio


169

ตอนนี้ Android Studio รองรับสินทรัพย์แบบเวกเตอร์ในวันที่ 21+ และจะสร้าง pngs สำหรับเวอร์ชั่นที่ต่ำกว่าในเวลารวบรวม ฉันมีสินทรัพย์แบบเวกเตอร์ (จากไอคอนวัสดุ) ที่ฉันต้องการเปลี่ยนสีเติม สิ่งนี้ใช้ได้กับ 21+ แต่ pngs ที่สร้างขึ้นจะไม่เปลี่ยนสี มีวิธีทำเช่นนี้หรือไม่?

<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>

คำตอบ:


333

อย่าแก้ไขเนื้อหาเวกเตอร์โดยตรง หากคุณกำลังใช้ drawable เวกเตอร์ใน ImageButton android:tintเพียงแค่เลือกสีของคุณใน

<ImageButton
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/button"
        android:src="@drawable/ic_more_vert_24dp"
        android:tint="@color/primary" />

24
ย้อมสีเพียง 21 + ทำงานบนอุปกรณ์ที่คุณมีข้อเสนอแนะใด ๆ สำหรับอุปกรณ์ก่อนอมยิ้ม
mudit

12
android: แต้มสีใช้งานได้กับ android ทุกรุ่นตั้งแต่ APIv1 สิ่งที่คุณหมายถึงคือ drawableTint
YYYY-MM-DD

31
android:tintต้องเป็นandroid:src
EmmanuelMess

5
สิ่งที่เกี่ยวกับdrawableLeftในButton?
Pratik Butani

8
@mudit ลองใช้เวกเตอร์ที่มี fillColor = "# colorvalue" อย่าใช้การอ้างอิง @ color เพราะมันใช้ได้เฉพาะ SDK 21+ สำหรับเวกเตอร์เท่านั้น (ดังนั้นไม่ใช่สำหรับ PNG ที่สร้างขึ้น)
PieterAelse

95

คุณสามารถทำมันได้.

แต่คุณไม่สามารถใช้การอ้างอิง @color สำหรับสี (..lame) มิฉะนั้นจะใช้งานได้กับ L + เท่านั้น

<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:fillColor="#FFAABB"
    android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>


11
นี่ควรเป็นคำตอบที่ยอมรับได้! การอ้างอิง @color ไม่ทำงานในเวกเตอร์ pre-Lollipop (ดังนั้นเวกเตอร์ -> การแปลง PNG) code.google.com/p/android/issues/detail?id=186431
PieterAelse

5
ขณะนี้สามารถใช้การอ้างอิง @color สำหรับแอตทริบิวต์ fillColor สำหรับ Android ทุกรุ่นได้ แต่ไม่รองรับรายการสถานะสี
TheIT

ดูเหมือนว่าวิธีการทำรายการสถานะเวกเตอร์อยู่กับAnimatedStateListDrawable s
gMale

1
@TheIT ฉันต้องเปิดใช้งานอะไร ดูเหมือนจะใช้งานไม่ได้สำหรับฉัน
urSus

@PieterAelse ฉันไม่แน่ใจว่าจะทำอย่างไรถ้าคุณต้องการใช้เนื้อหาเดียวกัน แต่มีภูมิหลังที่แตกต่างกัน (สีอ่อนเหมือนคำตอบก่อนหน้า) ในการแก้ปัญหาของคุณคุณจะมีทรัพยากรเดียวกันหลายครั้ง แต่มีสีเติมที่แตกต่างกัน
Anton Makov

71

ดังที่กล่าวไว้ในคำตอบอื่น ๆ อย่าแก้ไขเวกเตอร์ที่วาดได้โดยตรง แต่คุณสามารถแต้มสีในโค้ดจาวาได้เช่น:

    mWrappedDrawable = mDrawable.mutate();
    mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable);
    DrawableCompat.setTint(mWrappedDrawable, mColor);
    DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN);

และเพื่อความเรียบง่ายฉันได้สร้างคลาสผู้ช่วย:

import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

/**
 * {@link Drawable} helper class.
 *
 * @author Filipe Bezerra
 * @version 18/01/2016
 * @since 18/01/2016
 */
public class DrawableHelper {
    @NonNull Context mContext;
    @ColorRes private int mColor;
    private Drawable mDrawable;
    private Drawable mWrappedDrawable;

    public DrawableHelper(@NonNull Context context) {
        mContext = context;
    }

    public static DrawableHelper withContext(@NonNull Context context) {
        return new DrawableHelper(context);
    }

    public DrawableHelper withDrawable(@DrawableRes int drawableRes) {
        mDrawable = ContextCompat.getDrawable(mContext, drawableRes);
        return this;
    }

    public DrawableHelper withDrawable(@NonNull Drawable drawable) {
        mDrawable = drawable;
        return this;
    }

    public DrawableHelper withColor(@ColorRes int colorRes) {
        mColor = ContextCompat.getColor(mContext, colorRes);
        return this;
    }

    public DrawableHelper tint() {
        if (mDrawable == null) {
            throw new NullPointerException("É preciso informar o recurso drawable pelo método withDrawable()");
        }

        if (mColor == 0) {
            throw new IllegalStateException("É necessário informar a cor a ser definida pelo método withColor()");
        }

        mWrappedDrawable = mDrawable.mutate();
        mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable);
        DrawableCompat.setTint(mWrappedDrawable, mColor);
        DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN);

        return this;
    }

    @SuppressWarnings("deprecation")
    public void applyToBackground(@NonNull View view) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            view.setBackground(mWrappedDrawable);
        } else {
            view.setBackgroundDrawable(mWrappedDrawable);
        }
    }

    public void applyTo(@NonNull ImageView imageView) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        imageView.setImageDrawable(mWrappedDrawable);
    }

    public void applyTo(@NonNull MenuItem menuItem) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        menuItem.setIcon(mWrappedDrawable);
    }

    public Drawable get() {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        return mWrappedDrawable;
    }
}

หากต้องการใช้เพียงทำต่อไปนี้:

    DrawableHelper
            .withContext(this)
            .withColor(R.color.white)
            .withDrawable(R.drawable.ic_search_24dp)
            .tint()
            .applyTo(mSearchItem);

หรือ:

    final Drawable drawable = DrawableHelper
            .withContext(this)
            .withColor(R.color.white)
            .withDrawable(R.drawable.ic_search_24dp)
            .tint()
            .get();

    actionBar.setHomeAsUpIndicator(drawable);

สวัสดี Filipe ขอบคุณสำหรับคำตอบของคุณ คุณมีไลบรารี่, โค้ด github ที่เราสามารถดูไลเซนส์หรือไม่? ขอบคุณ :)
Vincent D.

2
Nope Vicent ไม่มีใบอนุญาตเลย วิธีแก้ปัญหามันง่ายมากที่ฉันเดาว่ารูปแบบตัวสร้างที่ใช้ในที่นี้ไม่จำเป็น แต่ทุกคนสามารถได้รับประโยชน์จากโซลูชันนี้และใช้งานโดยไม่มีใบอนุญาต
Filipe Bezerra de Sousa

คำตอบที่ดี! ทำงานเหมือนที่ฉันต้องการ
Eoin

1
@VincentD ส่วนท้ายของหน้าเว็บ SO พูดว่า "การมีส่วนร่วมของผู้ใช้ที่ได้รับอนุญาตภายใต้ cc by-sa 3.0 พร้อมการระบุแหล่งที่มา"
shelll

มันทำงานได้สำหรับฉันกับการเปลี่ยนแปลงบางอย่าง ขอขอบคุณสำหรับความช่วยเหลือของคุณ.
André Luiz Reis

36

ในการเปลี่ยนสีของภาพเวคเตอร์คุณสามารถใช้androidโดยตรง: tint = "@ color / colorAccent"

<ImageView
        android:id="@+id/ivVectorImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_account_circle_black_24dp"
        android:tint="@color/colorAccent" />

เพื่อเปลี่ยนสีโดยทางโปรแกรม

ImageView ivVectorImage = (ImageView) findViewById(R.id.ivVectorImage);
ivVectorImage.setColorFilter(getResources().getColor(R.color.colorPrimary));

getColor () เลิกใช้แล้ว
David

วิธีการใช้งานสำหรับ TextView ของ drawable ***?
Hemant Kaushik

getColor (ResId) เลิกใช้แล้ว @David แต่getColor(ResId, Theme)ไม่ใช่ หรือคุณสามารถใช้ResourcesCompat.getColor(getResources(), R.color.primary, null);หากคุณไม่สนใจเกี่ยวกับชุดรูปแบบ ... หรือถ้าผู้แทนบริบท / นโยบายของคุณเป็นกิจกรรมคุณสามารถทำได้getTheme()สำหรับพารามิเตอร์สุดท้ายนั้น
Martin Marconcini

15

ขณะนี้ soloution ที่ใช้งานได้คือ android: fillColor = "# FFFFFF"

ไม่มีอะไรทำงานให้ฉันยกเว้นการเข้ารหัสอย่างหนักในเวกเตอร์

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
      android:fillColor="#FFFFFF"
    android:viewportHeight="24.0">
<path
    android:fillColor="#FFFFFF"
    android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>

อย่างไรก็ตามสีเติมและสีอ่อนอาจใช้งานได้ในไม่ช้า โปรดดูการสนทนานี้สำหรับข้อมูลเพิ่มเติม:

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

นอกจากนี้สี mighr ยังติดอยู่ในแคชดังนั้นการลบแอพสำหรับผู้ใช้ทั้งหมดอาจช่วยได้


7

Android studio รองรับพรีอมอมโลฟเวกเตอร์แล้ว ไม่มีการแปลง PNG คุณยังสามารถเปลี่ยนสีเติมของคุณและมันจะทำงาน

ใน ImageView ของคุณให้ใช้

 app:srcCompat="@drawable/ic_more_vert_24dp"

ในไฟล์ gradle ของคุณ

 // Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
   }  
 }  

 compile 'com.android.support:design:23.4.0'

10
คำถามคือ "วิธีการเปลี่ยนสีเติมเวกเตอร์" ไม่ใช่ "วิธีใช้สินทรัพย์แบบเวกเตอร์"
Leo Droidcoder

5

อัปเดต: AppCompatรองรับ

คำตอบอื่น ๆ ที่สงสัยว่าandroid:tintจะใช้งานได้กับอุปกรณ์เพียง 21+ ตัวเท่านั้นตอนนี้AppCompat ( v23.2.0 ขึ้นไป )ให้การจัดการย้อนหลังของแอตทริบิวต์ tint

ดังนั้นหลักสูตรของการกระทำจะใช้AppCompatImageViewและapp:srcCompat(ใน AppCompat namespace) แทนandroid:src(Android namespace)

นี่คือตัวอย่าง (AndroidX: นี่คือandroidx.appcompat.widget.AppCompatImageView ;)):

<android.support.v7.widget.AppCompatImageView
        android:id="@+id/credits_material_icon"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:scaleType="fitCenter"
        android:tint="#ffd2ee"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:srcCompat="@drawable/ic_dollar_coin_stack" />

และอย่าลืมเปิดใช้งานการสนับสนุนเวกเตอร์ที่วาดได้ในระดับเสียง:

vectorDrawables.useSupportLibrary = true 

เพียงแค่อัปเดต ทุกวันนี้AppCompatImageViewอยู่ภายใต้การดูแลของandroidx.appcompat.widget.AppCompatImageView
โบโรนาต

2

เพิ่มไลบรารี่นี้ลงใน Gradle เพื่อเปิดใช้งานการวาดภาพเวกเตอร์สีในอุปกรณ์ Android รุ่นเก่า

compile 'com.android.support:palette-v7:26.0.0-alpha1'

และซิงค์ gradle อีกครั้ง ฉันคิดว่ามันจะแก้ปัญหา


2

หากเวกเตอร์ไม่แสดงสีที่ตั้งค่าเป็นรายบุคคลโดยใช้ fillColor พวกเขาอาจจะถูกตั้งค่าเป็นพารามิเตอร์เครื่องมือเริ่มต้น

ลองเพิ่มapp:itemIconTint="@color/lime"ใน activity_main.xml เพื่อตั้งค่าประเภทสีเริ่มต้นสำหรับไอคอนวิดเจ็ต

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:itemIconTint="@color/lime"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

VectorDrawable @ developers.android


ใน Android studio 3.6 การเปลี่ยนแปลงใน svg xml ฟิลด์นี้: android: fillColor = "# FFFFC400"
a_subscriber

1

ถ้าคุณมองหาการสนับสนุนรุ่นเก่าก่อน

ใช้รหัส xml เดียวกันกับการเปลี่ยนแปลงบางอย่าง

แทนที่จะเป็นเรื่องปกติ ImageView --> AppCompatImageView

แทน android:src --> app:srcCompat

นี่คือตัวอย่าง

<android.support.v7.widget.AppCompatImageView
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/button"
        app:srcCompat="@drawable/ic_more_vert_24dp"
        android:tint="@color/primary" />

อย่าลืมอัปเดตระดับของคุณในขณะที่ @ Sayooj Valsanพูดถึง

// Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
   }  
 }  

 compile 'com.android.support:design:23.4.0'

การแจ้งให้ทราบ ถึงเวกเตอร์ใด ๆ ที่ใช้ไม่เคยไม่เคยให้การอ้างอิงเวกเตอร์ของคุณกับสีเช่นนี้android:fillColor="@color/primary"ให้ค่า hex


ทำไมไม่เคยใช้@colorสำหรับfillcolor?
HoseinIT

0

สำหรับผู้ที่ไม่ได้ใช้ImageViewงานสิ่งต่อไปนี้ใช้ได้กับฉันบนพื้นราบView(และด้วยเหตุนี้พฤติกรรมจึงควรทำซ้ำในมุมมองทุกประเภท)

<View
    android:background="@drawable/ic_reset"
    android:backgroundTint="@color/colorLightText" />
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.