Как программно закруглить углы и задать случайные цвета фона

115

Я хотел бы скруглить углы представления, а также изменить цвет представления в зависимости от содержимого во время выполнения.

TextView v = new TextView(context);
v.setText(tagsList.get(i));
if(i%2 == 0){
    v.setBackgroundColor(Color.RED);
}else{
    v.setBackgroundColor(Color.BLUE);
}

v.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
v.setPadding(twoDP, twoDP, twoDP, twoDP);               
v.setBackgroundResource(R.drawable.tags_rounded_corners);

Я надеялся установить возможность рисования и цвета перекрываться, но это не так. То, что я выполню вторым, будет фоном.

Есть ли способ программно создать это представление, имея в виду, что цвет фона не будет определен до времени выполнения?

edit: я только меняю местами между красным и синим для тестирования. Позже цвет будет выбираться пользователем.

редактировать:

tags_rounded_corners.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <corners 
         android:bottomRightRadius="2dp" 
         android:bottomLeftRadius="2dp" 
         android:topLeftRadius="2dp" 
         android:topRightRadius="2dp"/>
</shape>
Джон Моффитт
источник
Конечно, цвет фона и фоновое изображение перекрывают друг друга. Чего вы пытаетесь достичь? Что есть tags_rounded_corners?
Alex MDC
Не могли бы вы показать еще коды? Это выглядит нормально, поэтому мне интересно, что вы можете использовать вид listView или повторно использовать существующее текстовое представление.
Chansuk

Ответы:

211

Вместо этого setBackgroundColorизвлеките фон, который можно рисовать, и установите его цвет:

v.setBackgroundResource(R.drawable.tags_rounded_corners);

GradientDrawable drawable = (GradientDrawable) v.getBackground();
if (i % 2 == 0) {
  drawable.setColor(Color.RED);
} else {
  drawable.setColor(Color.BLUE);
}

Кроме того, вы можете определить отступы в своем tags_rounded_corners.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <corners android:radius="4dp" />
  <padding
    android:top="2dp"
    android:left="2dp"
    android:bottom="2dp"
    android:right="2dp" />
</shape> 
chiuki
источник
Прямой ответ! он также работал с обводкой, но можем ли мы сделать это, используя что-то вроде colorDrawable = resources.getDrawable (R.drawable.x_sd_circle); colorDrawable.setColorFilter (цвет, PorterDuff.Mode.SRC_ATOP); если у нас нет границы. Но в случае границы, не могли бы вы сообщить мне PorterDuff.Mode, чтобы цвет обводки не изменился?
Ахил Папа
Как добавить цвет фона через XML?
Lenin Raj Rajasekaran
2
Если «v» - это TextView, то v.getBackground () будет приводить «java.lang.ClassCastException: android.graphics.drawable.StateListDrawable не может быть преобразовано в android.graphics.drawable.GradientDrawable». Это действительно работало в '13?
sonavolob
@sonavolob ты прав. это дает ClassCastException
Аднан
Идеальное решение! Спасибо!
Бот
126

Тотальный программный подход к закругленным углам и добавлению случайного цвета фона к представлению. Я не тестировал код, но вы поняли.

 GradientDrawable shape =  new GradientDrawable();
 shape.setCornerRadius( 8 );

 // add some color
 // You can add your random color generator here
 // and set color
 if (i % 2 == 0) {
  shape.setColor(Color.RED);
 } else {
  shape.setColor(Color.BLUE);
 }

 // now find your view and add background to it
 View view = (LinearLayout) findViewById( R.id.my_view );
 view.setBackground(shape);

Здесь мы используем градиент, который можно рисовать, чтобы мы могли его использовать, GradientDrawable#setCornerRadiusпотому что ShapeDrawableНЕ предоставляет никаких таких методов.

JaydeepW
источник
13
shape.setCornerRadii (углы); это очень полезно
umesh 01
14
Рассмотрите возможность использования PaintDrawableвместо GradientDrawable. Он поддерживает закругленные углы и только один цвет, который кажется более подходящим, чем градиент.
Cimlman
2
Это хорошо работает! Я использую его в Xamarin. var pd = new PaintDrawable(BackgroundColor); pd.SetCornerRadius(15); myView.Background = pd;
Пьер
Хорошее быстрое решение, но обратите внимание, что для него требуется API минимального уровня 16
Неизвестный разработчик
как установить радиус угла только для одной стороны?
Anonymous-E
10

Я думаю, что самый быстрый способ сделать это:

GradientDrawable gradientDrawable = new GradientDrawable(
            GradientDrawable.Orientation.TOP_BOTTOM, //set a gradient direction 
            new int[] {0xFF757775,0xFF151515}); //set the color of gradient
gradientDrawable.setCornerRadius(10f); //set corner radius

//Apply background to your view
View view = (RelativeLayout) findViewById( R.id.my_view );
if(Build.VERSION.SDK_INT>=16)
     view.setBackground(gradientDrawable);
else view.setBackgroundDrawable(gradientDrawable);    
Нолеш
источник
9

Вы можете лучше добиться этого, используя DrawableCompat следующим образом:

Drawable backgroundDrawable = view.getBackground();             
DrawableCompat.setTint(backgroundDrawable, newColor);
Алесио Карвалью
источник
5

Если у вас нет инсульта, вы можете использовать

colorDrawable = resources.getDrawable(R.drawable.x_sd_circle); 

colorDrawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);

но это также изменит цвет обводки

Ахил Папа
источник
39
Я собирался использовать это, но у меня инсульт.
Тим Малсид
2

Вот пример использования расширения. Это предполагает, что вид имеет одинаковую ширину и высоту.

Чтобы получить размер представления, необходимо использовать прослушиватель изменения макета. Тогда вы можете просто назвать это в таком видеmyView.setRoundedBackground(Color.WHITE)

fun View.setRoundedBackground(@ColorInt color: Int) {
    addOnLayoutChangeListener(object: View.OnLayoutChangeListener {
        override fun onLayoutChange(v: View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {

            val shape = GradientDrawable()
            shape.cornerRadius = measuredHeight / 2f
            shape.setColor(color)

            background = shape

            removeOnLayoutChangeListener(this)
        }
    })
}
Markymark
источник
1

Вы можете динамически изменять цвет любых элементов (макет, текст). Попробуйте ниже код, чтобы программно установить цвет в макете

в файле activity.java


String quote_bg_color = "#FFC107"
quoteContainer= (LinearLayout)view.findViewById(R.id.id_quotecontainer);
quoteContainer.setBackgroundResource(R.drawable.layout_round);
GradientDrawable drawable = (GradientDrawable) quoteContainer.getBackground();
drawable.setColor(Color.parseColor(quote_bg_color));

создать layout_round.xml в папке с возможностью переноса

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/colorPrimaryLight"/>
    <stroke android:width="0dp" android:color="#B1BCBE" />
    <corners android:radius="10dp"/>
    <padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

макет в файле activity.xml

<LinearLayout
        android:id="@+id/id_quotecontainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

----other components---

</LinearLayout>

страстный
источник
1

Копирование комментария @ cimlman в ответ верхнего уровня для большей наглядности:

PaintDrawable(Color.CYAN).apply {
  setCornerRadius(24f)
}

FYI: ShapeDrawable(и его подтип PaintDrawable) использует внутреннюю ширину и высоту по умолчанию, равные 0. Если объект для рисования не отображается в вашем сценарии использования, возможно, вам придется установить размеры вручную:

PaintDrawable(Color.CYAN).apply {
  intrinsicWidth = -1
  intrinsicHeight = -1
  setCornerRadius(24f)
}

-1- это магическая константа, которая указывает, что Drawable не имеет собственной ширины и высоты ( Источник ).

Сакет
источник