ตั้งค่าสีรูปร่างหุ่นยนต์โดยทางโปรแกรม


168

ฉันกำลังแก้ไขเพื่อทำให้คำถามง่ายขึ้นโดยหวังว่าจะช่วยให้ได้คำตอบที่ถูกต้อง

บอกว่าฉันมีovalรูปร่างดังต่อไปนี้:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:angle="270"
           android:color="#FFFF0000"/>
    <stroke android:width="3dp"
            android:color="#FFAA0055"/>
</shape>

ฉันจะตั้งค่าสีโดยทางโปรแกรมจากภายในคลาสกิจกรรมได้อย่างไร


สิ่งใดที่คุณตั้งค่า drawable นี้เป็น?
Vikram

drawable คือovalและเป็นพื้นหลังของ ImageView
Cote Mounyo

หากคำถามนี้ถามยากเกินไปมีวิธีการวาดภาพหลายภาพลงบนผืนผ้าใบและตั้งค่าผลิตภัณฑ์สุดท้ายที่เลเยอร์เป็นพื้นหลังของมุมมองหรือไม่?
Cote Mounyo

คุณสามารถทำได้โดยขยายViewคลาสและใช้เป็นbaseมุมมองในโครงร่างที่อนุญาตให้มีการซ้อนกันของวิดเจ็ต ( RelativeLayout, FrameLayout) ภายในขยายนี้ชั้นที่คุณสามารถView draw multiple images onto a canvasแต่ก่อนที่จะทำเช่นนั้นดูที่ -> ลิงค์ (ถ้าคุณยังไม่ได้)
Vikram

คำตอบ:


266

หมายเหตุ : คำตอบที่ได้รับการปรับปรุงเพื่อให้ครอบคลุมสถานการณ์ที่เป็นตัวอย่างของbackground ColorDrawableขอบคุณTyler Pfaffสำหรับการชี้ให้เห็น

drawable เป็นรูปวงรีและเป็นพื้นหลังของ ImageView

รับDrawableจากการimageViewใช้getBackground():

Drawable background = imageView.getBackground();

ตรวจสอบผู้ต้องสงสัยตามปกติ:

if (background instanceof ShapeDrawable) {
    // cast to 'ShapeDrawable'
    ShapeDrawable shapeDrawable = (ShapeDrawable) background;
    shapeDrawable.getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    // cast to 'GradientDrawable'
    GradientDrawable gradientDrawable = (GradientDrawable) background;
    gradientDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    // alpha value may need to be set again after this call
    ColorDrawable colorDrawable = (ColorDrawable) background;
    colorDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

รุ่นกะทัดรัด:

Drawable background = imageView.getBackground();
if (background instanceof ShapeDrawable) {
    ((ShapeDrawable)background).getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    ((GradientDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    ((ColorDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

โปรดทราบว่าไม่จำเป็นต้องมีการตรวจสอบ null

อย่างไรก็ตามคุณควรใช้mutate()กับ drawable ก่อนที่จะแก้ไขหากใช้ในที่อื่น (โดยค่าเริ่มต้น drawable ที่โหลดจาก XML จะใช้สถานะเดียวกัน)


3
ขอบคุณสำหรับคำตอบ. (+1) รหัสของฉันกำลังพบข้อบกพร่องอื่น ๆ ดังนั้นจึงเป็นการยากที่จะทดสอบ แต่ยังคงนี้อาจกำหนดsolidส่วนของรูปร่าง วิธีการเกี่ยวกับstrokeส่วน?
Cote Mounyo

1
@TiGer คุณควรเพิ่ม@usernameความคิดเห็นของคุณเพื่อให้แน่ใจว่ามีการส่งการแจ้งเตือนไปยังผู้ใช้ โดยวิธีการที่คุณจะต้อง subclass ShapeDrawableเพื่อกำหนดส่วนจังหวะ ข้อมูลเพิ่มเติมที่นี่: การเชื่อมโยง ดูความคิดเห็นที่กล่าวถึงปัญหากับคำตอบที่ยอมรับ
Vikram

3
android.graphics.drawable.GradientDrawable ไม่สามารถส่งไปยัง android.graphics.drawable.ShapeDrawable นักแสดงล้มเหลวในตัวฉัน
John

3
@ John หากImageView'sพื้นหลังถูกตั้งGradientDrawable, จะไม่กลับมาเป็นgetBackground() ShapeDrawableแทนที่จะใช้GradientDrawableที่ถูกส่งกลับ: ....GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground(); gradientDrawable.setColors(new int[] { color1, color2 });
Vikram

2
ขอบคุณ .. ช่วยโลกของฉัน
sid_09

43

ทำเช่นนี้:

    ImageView imgIcon = findViewById(R.id.imgIcon);
    GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
    backgroundGradient.setColor(getResources().getColor(R.color.yellow));

1
@ user3111850 คุณเพิ่มandroid:backgroundใน xml ของคุณหรือแม้กระทั่งsetBackgroundในกิจกรรมก่อนที่จะโทรgetBackground()? มันควรจะทำงานได้ถ้าคุณทำเช่นนั้น
Lee Yi Hong

41

วิธีแก้ปัญหาที่ง่ายกว่าในปัจจุบันคือการใช้รูปร่างของคุณเป็นพื้นหลังจากนั้นโปรแกรมเปลี่ยนสีโดยทางโปรแกรม:

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

ดูPorterDuff.Modeสำหรับตัวเลือกที่มี

อัปเดต (API 29):

วิธีการข้างต้นเลิกใช้แล้วตั้งแต่ API 29 และถูกแทนที่ด้วยสิ่งต่อไปนี้:

view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)

ดูBlendModeสำหรับตัวเลือกที่มี


4
สิ่งที่ถูกต้องคือ: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);เนื่องจากอาจมีเส้นขอบบนพื้นหลังหรือมุมที่โค้งมน
Berkay Turancı

1
Nice one @ BerkayTurancıรูปร่างของฉันมีมุมโค้งมน ฉันไม่ได้รับgetBackground()สาย imageview.src ของฉันมีรูปร่างและฉันใช้: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);ซึ่งtoggleColorเป็นเพียง int ที่ก่อนหน้านี้เก็บผลลัพธ์จาก getColor ()
บางคนที่ไหนสักแห่ง

1
มีPorterDuff.Modeสำหรับจะไม่รวบรวมตามที่ต้องการBlendModeColorFilter BlendModeดังนั้นสำหรับ API 29 view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)มันควรจะเป็น
Onik

เยี่ยมมาก @Onik ฉันได้อัพเดตคำตอบแล้ว ขอบคุณ!
Georgios

14

ลองสิ่งนี้:

 public void setGradientColors(int bottomColor, int topColor) {
 GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]  
 {bottomColor, topColor});
 gradient.setShape(GradientDrawable.RECTANGLE);
 gradient.setCornerRadius(10.f);
 this.setBackgroundDrawable(gradient);
 }

สำหรับรายละเอียดเพิ่มเติมตรวจสอบลิงค์นี้

หวังว่าจะช่วย


โหวตให้กับลิงค์ แต่มันไม่ใช่คำตอบสำหรับคำถามของฉัน
Cote Mounyo

13

หวังว่าสิ่งนี้จะช่วยคนที่มีปัญหาเดียวกัน

GradientDrawable gd = (GradientDrawable) YourImageView.getBackground();
//To shange the solid color
gd.setColor(yourColor)

//To change the stroke color
int width_px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, youStrokeWidth, getResources().getDisplayMetrics());
gd.setStroke(width_px, yourColor);

1
เริ่มแรกฉันไม่สามารถใช้งานได้ฉันคิดว่าสีของคุณต้องได้รับดังนี้:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce

12

ขยายคำตอบของ Vikramหากคุณกำลังระบายสีมุมมองแบบไดนามิกเช่นรายการมุมมอง recycler ฯลฯ .... จากนั้นคุณอาจต้องการเรียกใช้ mutate () ก่อนที่คุณจะตั้งค่าสี หากคุณไม่ทำเช่นนี้มุมมองใด ๆ ที่มี drawable ทั่วไป (เช่นพื้นหลัง) จะมีการเปลี่ยนแปลง / สีที่สามารถวาดได้

public static void setBackgroundColorAndRetainShape(final int color, final Drawable background) {

    if (background instanceof ShapeDrawable) {
        ((ShapeDrawable) background.mutate()).getPaint().setColor(color);
    } else if (background instanceof GradientDrawable) {
        ((GradientDrawable) background.mutate()).setColor(color);
    } else if (background instanceof ColorDrawable) {
        ((ColorDrawable) background.mutate()).setColor(color);
    }else{
        Log.w(TAG,"Not a valid background type");
    }

}

3
ความต้องการและการตรวจสอบพิเศษและพารามิเตอร์: การจัดการกับพื้นหลังรูปแบบที่ใช้งานif (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...] <layer-list ... <item ...
Johny

11

คำถามนี้ได้รับคำตอบในขณะที่กลับ แต่มันสามารถทำให้ทันสมัยโดยการเขียนใหม่เป็นฟังก์ชั่นส่วนขยาย kotlin

fun Drawable.overrideColor(@ColorInt colorInt: Int) {
    when (this) {
        is GradientDrawable -> setColor(colorInt)
        is ShapeDrawable -> paint.color = colorInt
        is ColorDrawable -> color = colorInt
    }
}

7

นี่เป็นวิธีแก้ปัญหาที่เหมาะกับฉัน ... เขียนในคำถามอื่นด้วย: จะเปลี่ยนสีของรูปร่างได้อย่างไร?

//get the image button by id
ImageButton myImg = (ImageButton) findViewById(R.id.some_id);

//get drawable from image button
GradientDrawable drawable = (GradientDrawable) myImg.getDrawable();

//set color as integer
//can use Color.parseColor(color) if color is a string
drawable.setColor(color)

4

ไม่มีอะไรทำงานได้สำหรับฉัน แต่เมื่อฉันตั้งค่าสีอ่อนมันจะทำงานกับ Shape Drawable

 Drawable background = imageView.getBackground();
 background.setTint(getRandomColor())

ต้องใช้ Android 5.0 API 21


3

รุ่นฟังก์ชั่นเสริมของฉันKotlinขึ้นอยู่กับคำตอบข้างต้นด้วยความเข้ากันได้:

fun Drawable.overrideColor_Ext(context: Context, colorInt: Int) {
    val muted = this.mutate()
    when (muted) {
        is GradientDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        is ShapeDrawable -> muted.paint.setColor(ContextCompat.getColor(context, colorInt))
        is ColorDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        else -> Log.d("Tag", "Not a valid background type")
    }
}

1

วิธีง่ายๆในการเติมรูปร่างด้วยรัศมีคือ:

(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);

1

อาจเป็นฉันสายเกินไป แต่ถ้าคุณใช้ Kotlin มีวิธีเช่นนี้

var gd = layoutMain.background as GradientDrawable

 //gd.setCornerRadius(10)
  gd.setColor(ContextCompat.getColor(ctx , R.color.lightblue))
  gd.setStroke(1, ContextCompat.getColor(ctx , R.color.colorPrimary)) // (Strokewidth,colorId)

สนุก....


0

สำหรับใครก็ตามที่ใช้ C # Xamarin ต่อไปนี้เป็นวิธีการตามตัวอย่างของ Vikram:

private void SetDrawableColor(Drawable drawable, Android.Graphics.Color color)
{
    switch (drawable)
    {
        case ShapeDrawable sd:
            sd.Paint.Color = color;
            break;
        case GradientDrawable gd:
            gd.SetColor(color);
            break;
        case ColorDrawable cd:
            cd.Color = color;
            break;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.