Đặt màu cho hình dạng Android theo chương trình


168

Tôi đang chỉnh sửa để làm cho câu hỏi đơn giản hơn, hy vọng điều đó sẽ giúp hướng tới một câu trả lời chính xác.

Nói rằng tôi có ovalhình dạng sau :

<?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>

Làm cách nào để đặt màu lập trình, từ trong một lớp hoạt động?


Bạn đặt cái này có thể vẽ được là gì?
Vikram

Drawable là một ovalvà là nền tảng của ImageView.
Côte Mounyo

Nếu câu hỏi này khi được hỏi quá khó, có cách nào để vẽ nhiều hình ảnh lên một khung vẽ và đặt sản phẩm cuối được xếp lớp làm nền của chế độ xem không?
Côte Mounyo

Bạn có thể đạt được điều này bằng cách mở rộng Viewlớp và sử dụng nó làm dạng basexem trong bố cục cho phép chồng lấp các widget ( RelativeLayout, FrameLayout). Trong Viewlớp mở rộng này , bạn có thể draw multiple images onto a canvas. Nhưng, trước khi làm điều đó, hãy xem cái này -> Liên kết (nếu bạn chưa có).
Vikram

Câu trả lời:


266

Lưu ý : Câu trả lời đã được cập nhật để bao gồm các tình huống trong đó backgroundlà một ví dụ ColorDrawable. Cảm ơn Tyler Pfaff , vì đã chỉ ra điều này.

Drawable là một hình bầu dục và là nền của ImageView

Nhận Drawabletừ imageViewviệc sử dụng getBackground():

Drawable background = imageView.getBackground();

Kiểm tra đối với các nghi phạm thông thường:

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));
}

Phiên bản nhỏ gọn:

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));
}

Lưu ý rằng kiểm tra null là không cần thiết.

Tuy nhiên, bạn nên sử dụng mutate()trên các drawable trước khi sửa đổi chúng nếu chúng được sử dụng ở nơi khác. (Theo mặc định, các drawable được tải từ XML có cùng trạng thái.)


3
Cảm ơn đã trả lời. (+1). Mã của tôi đang gặp các lỗi khác nên rất khó kiểm tra. Nhưng điều này vẫn có thể thiết lập một solidphần của hình dạng. Làm thế nào về strokephần?
Côte Mounyo

1
@TiGer Bạn nên thêm @usernamevào bình luận của mình để đảm bảo thông báo được gửi đến người dùng. Nhân tiện, bạn sẽ cần phải phân lớp ShapeDrawableđể đặt phần đột quỵ. Thêm thông tin ở đây: Liên kết . Nhìn vào bình luận vì nó đề cập đến một vấn đề với câu trả lời được chấp nhận.
Vikram

3
android.graphics.drawable.GradientDrawable không thể được chuyển thành android.graphics.drawable.ShapeDrawable Các diễn viên thất bại với tôi
John

3
@ John Nếu ImageView'snền của bạn được đặt thành a GradientDrawable, getBackground()sẽ không trả về a ShapeDrawable. Thay vào đó, sử dụng GradientDrawableđược trả về: GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();.... gradientDrawable.setColors(new int[] { color1, color2 });.
Vikram

2
Cảm ơn .. đã cứu thế giới của tôi.
sid_09

43

Làm như thế này:

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

1
@ user3111850 Bạn đã thêm android:backgroundvào xml hoặc thậm chí setBackgroundtrong hoạt động trước khi gọi getBackground()? Nó sẽ hoạt động nếu bạn đã làm như vậy.
Lee Yi Hong

41

Một giải pháp đơn giản hơn hiện nay là sử dụng hình dạng của bạn làm nền và sau đó lập trình thay đổi màu sắc của nó thông qua:

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

Xem PorterDuff.Mode để biết các tùy chọn có sẵn.

CẬP NHẬT (API 29):

Phương pháp trên không được dùng nữa kể từ API 29 và được thay thế bằng cách sau:

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

Xem BlendMode cho các tùy chọn có sẵn.


4
Đúng một là: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);Vì có thể có một đường viền trên nền hoặc sân tròn.
Berkay Turancı

1
Một người đẹp @ BerkayTurancı hình của tôi đã có những góc tròn. Tôi có thể bỏ qua getBackground()cuộc gọi. Imageview.src của tôi chứa một hình dạng và tôi đã sử dụng: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);nơi toggleColorchỉ là một int đã lưu kết quả trước đó từ getColor ()
Ai đó ở đâu đó vào

1
PorterDuff.Modecho BlendModeColorFiltersẽ không biên dịch như nó yêu cầu BlendMode. Vì vậy, đối với API 29 thì phải như vậy view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP).
Onik

Bắt tốt @Onik. Tôi đã cập nhật câu trả lời tương ứng. Cảm ơn bạn!
Georgios

14

Thử cái này:

 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);
 }

để biết thêm chi tiết kiểm tra liên kết này

mong được giúp đỡ


bỏ phiếu cho các liên kết. Nhưng nó không phải là câu trả lời cho câu hỏi của tôi.
Côte Mounyo

13

hy vọng điều này sẽ giúp ai đó có cùng vấn đề

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
Ban đầu tôi không thể làm việc này được, tôi nhận ra Màu sắc của bạn phải được cung cấp như thế này:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce

12

Mở rộng câu trả lời của Vikram , nếu bạn đang tô màu các chế độ xem động, như các mục xem tái chế, v.v .... Sau đó, bạn có thể muốn gọi mutate () trước khi bạn đặt màu. Nếu bạn không làm điều này, bất kỳ chế độ xem nào có thể vẽ chung (ví dụ: nền) cũng sẽ có thể thay đổi / tô màu có thể vẽ được.

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
nhu cầu và kiểm tra thêm và tham số: if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...]để đối phó với bố cục nền sử dụng <layer-list ... <item ....
Johny

11

Câu hỏi này đã được trả lời một lúc trước, nhưng nó có thể được hiện đại hóa bằng cách viết lại dưới dạng hàm mở rộng kotlin.

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

7

đây là giải pháp phù hợp với tôi ... cũng đã viết nó trong một câu hỏi khác: Làm thế nào để thay đổi màu sắc linh hoạt?

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

Không có gì phù hợp với tôi nhưng khi tôi đặt màu, nó hoạt động trên Shape Drawable

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

yêu cầu Android 5.0 API 21


3

Phiên bản chức năng mở rộng Kotlin của tôi dựa trên các câu trả lời ở trên với Compat :

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

Cách đơn giản để điền vào hình dạng với Bán kính là:

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

1

Có thể tôi đã quá muộn. Nhưng nếu bạn đang sử dụng Kotlin. Có cách như thế này

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)

Thưởng thức....


0

Đối với bất kỳ ai sử dụng C # Xamarin, đây là một phương pháp dựa trên đoạn trích của 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;
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.