เปลี่ยนสีที่วาดได้โดยทางโปรแกรม


149

ฉันกำลังพยายามเปลี่ยนสีบนภาพเครื่องหมายสีขาวด้วยรหัส ฉันได้อ่านว่าโค้ดด้านล่างควรเปลี่ยนสี แต่เครื่องหมายของฉันยังคงเป็นสีขาว

Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )

ฉันพลาดอะไรไปหรือเปล่า? มีวิธีอื่นในการเปลี่ยนสีบน drawables ที่อยู่ในโฟลเดอร์ res ของฉันหรือไม่?


คำตอบที่ยอมรับไม่ได้ผลสำหรับฉัน .. ใช้วิธีการตอบนี้ [1], [1]: stackoverflow.com/questions/5940825/…
sham.y

ฉันคิดว่าคำตอบทั้งหมดที่นี่จะเปลี่ยนสีพื้นหลัง แต่ไม่ใช่สีของภาพ ฉันใช่ไหม ใครช่วยบอกฉันที ฉันลองใช้วิธีแก้ปัญหาทั้งหมดที่นี่และคำถามเดียวกันใน stackoverflow แต่ในกรณีอาจเปลี่ยนเฉพาะสีพื้นหลัง ฉันคิดว่าเราสามารถเปลี่ยนสีพื้นหลังได้เท่านั้น แต่ไม่สามารถเปลี่ยนสีของภาพได้ ฉันใช่ไหม
Shirish Herwade

คำตอบ:


275

ลองสิ่งนี้:

Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, R.drawable.my_drawable); 
Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(wrappedDrawable, Color.RED);    

การใช้งานDrawableCompatมีความสำคัญเนื่องจากให้ความเข้ากันได้แบบย้อนหลังและแก้ไขข้อบกพร่องบนอุปกรณ์ API 22 และรุ่นก่อนหน้า


อืมสียังขาวอยู่ อาจเกี่ยวข้องกับOverlayItemsคลาสhello mapview ที่อาจทำให้เกิดปัญหาหรือไม่ มันเป็นสิ่งที่ดึงได้จากโฟลเดอร์ res ของฉันไม่มีอะไรพิเศษ ...
Johan

แล้วทางออกคืออะไร?
speedynomads

30
คุณอาจชอบ PorterDuff.Mode.SRC_IN ถ้าคุณต้องการให้มันทำงานกับสีต้นทางที่หลากหลายกว่า
Lorne Laliberte

1
ตัวสร้าง PorterDuffColorFilter ใช้รูปแบบสี
ARGB

1
จะน่าสนใจที่จะกลายพันธุ์สิ่งที่วาดได้ด้วย #mutate () เพื่อหลีกเลี่ยงการแบ่งปันสถานะของมันกับสิ่งอื่น ๆ ที่วาดได้มิฉะนั้นหากคุณนำมาใช้ซ้ำอาจมีสีที่ไม่ถูกต้อง
Ricard

130

คุณสามารถลองสิ่งนี้สำหรับเวกเตอร์ svg ที่วาดได้

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

4
วิธีที่ดีที่สุดที่ฉันเคยเห็นสำหรับ svg
apSTRK

1
ชอบสิ่งนี้มากกว่าคำตอบที่ยอมรับแม้ว่าทั้งสองจะใช้งานได้ แต่ด้วยข้อนี้ฉันไม่ต้องกังวลว่าจะตั้งค่าอะไรได้ฉันเพิ่งได้คำตอบที่นั่นแล้วและยังเข้ากันได้แบบย้อนหลังอีกด้วยเยี่ยมมาก!
RJFares

1
คำตอบที่ดีที่สุดเมื่อไม่มีอะไรทำงานไอโอทีทำงานอย่างมีเสน่ห์! ขอบคุณมาก! หมายเหตุ: นอกจากนี้ยังใช้งานได้เมื่อคุณมี xml ที่วาดได้ใน imageView / AppCompatImageView
Sjd

1
จะลบออกโดยทางโปรแกรมได้อย่างไร?
Hardik Joshi

1
@HardikJoshi เอกสารระบุว่า: หากต้องการล้างโทนสีให้ส่งnullไปที่Drawable#setTintList(ColorStateList)
arekolek

26

คุณอาจต้องเรียก mutate () บน drawable มิฉะนั้นไอคอนทั้งหมดจะได้รับผลกระทบ

Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_my_icon).mutate();
TypedValue typedValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.colorIcon, typedValue, true);
icon.setColorFilter(typedValue.data, PorterDuff.Mode.SRC_ATOP);

21

อีกวิธีหนึ่งในการทำสิ่งนี้บน Lollipop, android 5. + คือการตั้งค่าสีบนบิตแมปที่วาดได้ดังนี้:

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_back"
    android:tint="@color/red_tint"/>

วิธีนี้จะใช้ได้ผลสำหรับคุณหากคุณมีสีจำนวน จำกัด ที่คุณต้องการใช้กับ drawables ของคุณ ตรวจสอบการโพสต์บล็อกของฉันสำหรับข้อมูลเพิ่มเติม


2
ดี! Btw ดูเหมือนว่าจะทำงานได้ดีกับ Pre-Lollipop ด้วย (เพิ่งทดสอบกับminSdkVersion 16อุปกรณ์ Android 4.1.1)
Jonik

android:background="..."เมื่อมีการสร้างบิตแมปด้วยวิธีนี้จะไม่ยืดให้พอดีกับรูปแบบในขณะที่มันจะเมื่อใช้ สวยแปลก!
เจ้าชาย

ฉันคิดว่านั่นเป็นเพราะคุณไม่ได้สร้างแพตช์เก้าตัวที่นี่
MinceMan

ขออภัยไม่มีหน้านี้ = (
Phan Van Linh

@Jonik คำตอบในคำถามของคุณไม่เกี่ยวข้อง คำถามนี้กำลังถามถึงวิธีการเปลี่ยนสีของDrawableไม่ใช่ ImageView
Antony.H


10

คุณสามารถลอง ColorMatrixColorFilter ได้เนื่องจากสีหลักของคุณเป็นสีขาว:

// Assuming "color" is your target color
float r = Color.red(color) / 255f;
float g = Color.green(color) / 255f;
float b = Color.blue(color) / 255f;

ColorMatrix cm = new ColorMatrix(new float[] {
        // Change red channel
        r, 0, 0, 0, 0,
        // Change green channel
        0, g, 0, 0, 0,
        // Change blue channel
        0, 0, b, 0, 0,
        // Keep alpha channel
        0, 0, 0, 1, 0,
});
ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
myDrawable.setColorFilter(cf);

ทำงานเมื่อสีเป้าหมายไม่โปร่งใส
Malachiasz

10

ฉันได้เขียนฟังก์ชั่นทั่วไปที่คุณสามารถส่งผ่านบริบทไอคอนคือ id drawable / ไอคอนรูปภาพ mipmap และสีใหม่ที่คุณต้องการสำหรับไอคอนนั้น

ฟังก์ชันนี้ส่งคืนค่าที่เบิกได้

public static Drawable changeDrawableColor(Context context,int icon, int newColor) {
    Drawable mDrawable = ContextCompat.getDrawable(context, icon).mutate(); 
    mDrawable.setColorFilter(new PorterDuffColorFilter(newColor, PorterDuff.Mode.SRC_IN)); 
    return mDrawable;
} 

changeDrawableColor(getContext(),R.mipmap.ic_action_tune, Color.WHITE);

7

สิ่งนี้ได้ผลสำหรับฉัน อย่าลืมใส่ "ff" ระหว่าง 0x และรหัสสี เช่นนี้ 0xff2196F3

Drawable mDrawable = ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_vector_home);
                    mDrawable.setColorFilter(new
                            PorterDuffColorFilter(0xff2196F3,PorterDuff.Mode.SRC_IN));

สวัสดี @Bek ยินดีต้อนรับสู่ stackoverflow หากสิ่งนี้ได้ผลสำหรับคุณการรวม jsfiddle เข้ากับโซลูชันขั้นต่ำจะเป็นประโยชน์มากเพื่อแสดงสิ่งนั้น จะช่วยให้ผู้ที่โพสต์คำถามเข้าใจอย่างถูกต้อง
Arjun Chaudhary

6

เช่นเดียวกับคำตอบที่ยอมรับ แต่เป็นวิธีที่ง่ายกว่า:

val myDrawable = ContextCompat.getDrawable(context, R.drawable.my_drawable)
myDrawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN)
setCompoundDrawablesWithIntrinsicBounds(myDrawable, null, null, null)

หมายเหตุรหัสที่นี่คือ Kotlin


3

คุณอาจต้องการที่จะลองหรือMode.LIGHTEN Mode.DARKENJavadocs ของ Android นั้นแย่มากในการอธิบายว่า PorterDuff Modes ทำอะไร คุณสามารถดูได้ที่นี่: PorterDuff | Android

ฉันขอแนะนำให้ดูที่ Compositing บนเว็บไซต์ของ Mozilla ที่นี่ (พวกเขาไม่มีโหมดทั้งหมดที่ Android มี แต่มีมากมาย)


3

ใช้สิ่งนี้: สำหรับ java

view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_OVER)

สำหรับ Kotlin

view.background.setColorFilter(Color.parseColor("#343434"),PorterDuff.Mode.SRC_OVER)

คุณสามารถใช้ PorterDuff.Mode.SRC_ATOP หากพื้นหลังของคุณมีมุมมนเป็นต้น


1

ไวยากรณ์

"your image name".setColorFilter("your context".getResources().getColor("color name"));

ตัวอย่าง

myImage.setColorFilter(mContext.getResources().getColor(R.color.deep_blue_new));

1

สำหรับผู้ที่ใช้ Kotlinฟังก์ชั่นการขยายอย่างง่าย:

fun Drawable.tint(context: Context,  @ColorRes color: Int) {
    DrawableCompat.setTint(this, context.resources.getColor(color, context.theme))
}

แล้วก็ทำ

background.tint(context, R.color.colorPrimary)

0

นี่คือสิ่งที่ฉันทำ:

public static Drawable changeDrawableColor(int drawableRes, int colorRes, Context context) {
    //Convert drawable res to bitmap
    final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableRes);
    final Bitmap resultBitmap = Bitmap.createBitmap(bitmap, 0, 0,
            bitmap.getWidth() - 1, bitmap.getHeight() - 1);
    final Paint p = new Paint();
    final Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, p);

    //Create new drawable based on bitmap
    final Drawable drawable = new BitmapDrawable(context.getResources(), resultBitmap);
    drawable.setColorFilter(new
            PorterDuffColorFilter(context.getResources().getColor(colorRes), PorterDuff.Mode.MULTIPLY));
    return drawable;
}

0

ใช้งานง่าย

    android:drawableTint="@color/primary_color"

ในไฟล์ XML ของคุณ แทนที่ primary_color เป็นสีที่กำหนดเอง


0

สร้างวิธีการดังนี้:

//CHANGE ICON COLOR
private void changeIconColor(Context context ,int drawable){
    Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, drawable);
    assert unwrappedDrawable != null;
    Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
    DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.colorAccent));
}

และใช้มันอย่างนี้:

    changeIconColor(this,R.drawable.ic_home);

0

วิธีที่ง่ายที่สุดในการทำ:

imageView.setColorFilter(Color.rgb(r, g b));

หรือ

imageView.setColorFilter(Color.argb(a, r, g, b));

a, r, g, b: ค่าสี argb


สิ่งนี้จะใช้ได้เฉพาะในกรณีที่ OP ใช้ imageViews แทน drawables
SowingFiber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.