2015-05-09 14 views
11

Ho cercato di rintracciare questo problema per un po 'di tempo. Penso di aver trovato una spiegazione qualche tempo fa. Sfortunatamente, è stato perso nei commenti di codice da qualche parte.RippleDrawable creato a livello di codice sembra diverso dalla sua controparte xml

Sto cercando di creare un Material Borderless-Button in Java. Per cominciare, ecco cosa il pulsante appare come nel quadro:

Pulsante bg (button_borderless_material.xml):

<?xml version="1.0" encoding="utf-8"?> 
<ripple xmlns:android="http://schemas.android.com/apk/res/android" 
     android:color="?attr/colorControlHighlight"> 
    <item android:id="@id/mask" 
     android:drawable="@drawable/btn_default_mtrl_shape" /> 
</ripple> 

Il drawable essere usato come maschera (btn_default_mtrl_shape.xml):

<?xml version="1.0" encoding="utf-8"?> 
<!-- Used as the canonical button shape. --> 
<inset xmlns:android="http://schemas.android.com/apk/res/android" 
     android:insetLeft="@dimen/button_inset_horizontal_material" 
     android:insetTop="@dimen/button_inset_vertical_material" 
     android:insetRight="@dimen/button_inset_horizontal_material" 
     android:insetBottom="@dimen/button_inset_vertical_material"> 
    <shape android:shape="rectangle" 
      android:tint="?attr/colorButtonNormal"> 
     <corners android:radius="@dimen/control_corner_material" /> 
     <solid android:color="@color/white" /> 
     <padding android:left="@dimen/button_padding_horizontal_material" 
       android:top="@dimen/button_padding_vertical_material" 
       android:right="@dimen/button_padding_horizontal_material" 
       android:bottom="@dimen/button_padding_vertical_material" /> 
    </shape> 
</inset> 

Java equivalente del inset-drawable (btn_default_mtrl_shape.xml):

Drawable createButtonShape(Context context, int color) { 
    Resource res = context.getResources(); 
    int radius = res 
      .getDimensionPixelSize(R.dimen.control_corner_material); 
    int paddingH = res 
      .getDimensionPixelSize(R.dimen.button_padding_horizontal_material); 
    int paddingV = res 
      .getDimensionPixelSize(R.dimen.button_padding_vertical_material); 
    int insetH = context.getResources() 
      .getDimensionPixelSize(R.dimen.button_inset_horizontal_material); 
    int insetV = res 
      .getDimensionPixelSize(R.dimen.button_inset_vertical_material); 

    float[] outerRadii = new float[8]; 
    Arrays.fill(outerRadii, radius); 

    RoundRectShape r = new RoundRectShape(outerRadii, null, null); 

    ShapeDrawable shapeDrawable = new ShapeDrawable(r); 
    shapeDrawable.getPaint().setColor(color); 
    shapeDrawable.setPadding(paddingH, paddingV, paddingH, paddingV); 

    return new InsetDrawable(shapeDrawable, 
      insetH, insetV, insetH, insetV); 
} 

L'argomento color è ottenuto dalla tema di attr/colorButtonNormal - lo stesso colore utilizzato con android:tint nella definizione XML.

Il RippleDrawable creato a livello di codice:

@TargetApi(Build.VERSION_CODES.LOLLIPOP) 
Drawable createButtonRippleBg(Context context, 
              int colorButtonNormal, 
              int colorControlHighlight) { 
    return new RippleDrawable(ColorStateList.valueOf(colorControlHighlight), 
        null, createButtonShape(context, colorButtonNormal)); 
} 

Sono consapevole del fatto che, anche se la maschera-colore/forma non è reso visivamente, la sua alfa fa influisce sulla RippleDrawable. Questo non è un problema qui: tutti i colori usati per la maschera hanno un alfa completo.

Ho anche confermato che i colori letti dagli attributi - colorControlHighlight & colorButtonNormal - sono corretti per il tema in gioco.

Tuttavia, il risultato è:

XML resa:

enter image description here

In Java:

enter image description here

bit interessante è che questo avviene API 21. API 22, entrambi gli approcci producono risultati identici.

La domanda:

Sono certo che si tratta di un bug su API 21. Se qualcuno può seguire questo giù, si può probabilmente trovare un moltiplicatore per il valore alfa/colore per compensare questa differenza visiva.

Oltre alla buona volontà generale, prometto anche un premio in quanto ho già trascorso un po 'di tempo su questo.

+0

L'unica differenza che vedo è che via XML di impostare il colore come tinta 'Android: "attr/colorButtonNormal" tinta =' e tramite codice si imposta come colore 'shapeDrawable. getPaint().setColor (color); ' – mikepenz

+0

@mikepenz Sì, l'argomento' color' è in realtà ottenuto da 'colorButtonNormal' del tema. L'ho detto sopra: _L'argomento 'color' è ottenuto dal tema' attr/colorButtonNormal' - lo stesso colore usato con 'android: tint' in xml definition_. – Vikram

+0

no, questa non è la cosa che intendo. Lo si imposta come colore 'shapeDrawable.getPaint(). SetColor (color)' nel xml come 'tint'. perché non impostarlo anche come tinta tramite codice? 'shapeDrawable.setTint();' – mikepenz

risposta

0

Prova questo costruttore alternativo new RippleDrawable(ColorStateList.valueOf(colorRipple), backgroundDrawable, null);