Como arredondar cantos programaticamente e definir cores de fundo aleatórias

114

Eu gostaria de arredondar os cantos de uma visualização e também alterar a cor da visualização com base no conteúdo em tempo de execução.

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

Eu esperava que a configuração de um drawable e as cores se sobreponham, mas isso não acontece. O que eu executar em segundo lugar é o fundo resultante.

Existe alguma maneira de criar essa visualização programaticamente, tendo em mente que a cor de fundo não será decidida até o tempo de execução?

editar: estou apenas trocando entre vermelho e azul agora para teste. Posteriormente, a cor será escolhida pelo usuário.

editar:

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>
John Moffitt
fonte
É claro que a cor de fundo e a imagem de fundo se sobrepõem. O que você está tentando alcançar? O que é tags_rounded_corners?
Alex MDC de
Você poderia mostrar mais códigos? Parece bom, então eu imagino que você pode usar o tipo de listView ou reutilizar o textview existente.
Chansuk de

Respostas:

211

Em vez de setBackgroundColor, recupere o drawable de plano de fundo e defina sua cor:

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

Além disso, você pode definir o preenchimento em 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
fonte
Perect responda! funcionou com strock também, mas podemos fazer isso usando algo como colorDrawable = resources.getDrawable (R.drawable.x_sd_circle); colorDrawable.setColorFilter (color, PorterDuff.Mode.SRC_ATOP); se não tivermos uma fronteira. Mas no caso de fronteira, você pode me informar o PorterDuff.Mode para que a cor do traço não mude
Akhil Dad
Como adicionar cor de fundo também via XML?
Lenin Raj Rajasekaran
2
Se "v" for o TextView, então v.getBackground () lançará "java.lang.ClassCastException: android.graphics.drawable.StateListDrawable não pode ser convertido para android.graphics.drawable.GradientDrawable" Isso estava realmente funcionando em '13?
sonavolob de
@sonavolob você está certo. dá ClassCastException
Adnan
A solução perfeita! Obrigado!
Bot de
124

Abordagem programática total para definir cantos arredondados e adicionar cor de fundo aleatória a uma visualização. Eu não testei o código, mas você entendeu.

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

Aqui estamos usando drawable gradiente para que possamos fazer uso GradientDrawable#setCornerRadiusporque ShapeDrawableNÃO fornece tal método.

JaydeepW
fonte
13
shape.setCornerRadii (cantos); é muito útil
umesh
14
Considere usar em PaintDrawablevez de GradientDrawable. Suporta cantos arredondados e apenas uma única cor, o que parece mais adequado do que um gradiente.
Cimlman
2
Isso funciona bem! Eu uso no Xamarin. var pd = new PaintDrawable(BackgroundColor); pd.SetCornerRadius(15); myView.Background = pd;
Pierre
Boa solução rápida, mas observe que requer API de nível mínimo 16
The Unknown Dev
como definir o raio do canto apenas para um lado?
Anônimo-E
10

Acho que a maneira mais rápida de fazer isso é:

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);    
Nolesh
fonte
9

Você pode alcançá-lo melhor usando DrawableCompat como este:

Drawable backgroundDrawable = view.getBackground();             
DrawableCompat.setTint(backgroundDrawable, newColor);
Alécio Carvalho
fonte
5

Se você não está tendo um derrame, você pode usar

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

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

mas isso também mudará a cor do traço

Akhil Pai
fonte
39
Eu ia usar isso, mas estou tendo um derrame.
Tim Malseed
2

Aqui está um exemplo usando uma extensão. Isso pressupõe que a visualização tem a mesma largura e altura.

É necessário usar um ouvinte de mudança de layout para obter o tamanho da visualização. Então você pode simplesmente chamá-lo em uma vista como estamyView.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
fonte
1

Você pode alterar dinamicamente a cor de qualquer item (layout, textview). Experimente o código abaixo para definir as cores de maneira programática no layout

no arquivo 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));

crie layout_round.xml na pasta drawable

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

layout no arquivo activity.xml

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

----other components---

</LinearLayout>

evops apaixonados
fonte
1

Copiar o comentário de @cimlman em uma resposta de nível superior para obter mais visibilidade:

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

Para ShapeDrawablesua informação: (e seu subtipo, PaintDrawable) usa largura intrínseca padrão e altura de 0. Se o drawable não aparecer em seu caso de uso, você pode ter que definir as dimensões manualmente:

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

-1é uma constante mágica que indica que um Drawable não tem largura e altura intrínsecas próprias ( Fonte ).

Saket
fonte