2015-05-09 8 views
11

Od jakiegoś czasu próbuję prześledzić ten problem. Chyba znalazłem jakieś wyjaśnienie jakiś czas temu. Niestety, zagubione w komentarzach kodu gdzieś.Program RippleDrawable programowo wygląda inaczej niż jego odpowiednik xml

Próbuję utworzyć Material Borderless-Button w Javie. Na początek, oto co przycisk wygląda w ramach:

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

drawable używany jako maska ​​(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 odpowiednik 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); 
} 

color argumentem jest otrzymywany z motywu attr/colorButtonNormal - tego samego koloru używanego z android:tint w definicji xml.

RippleDrawable tworzone programowo:

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

Zdaję sobie sprawę, że choć maska-kolor/kształt nie jest renderowany wizualnie, jego alfa ma wpływa na RippleDrawable. To nie jest problem - wszystkie kolory używane w masce mają pełnowymiarową alfę.

Potwierdziłem również, że kolory odczytane z atrybutów - colorControlHighlight & colorButtonNormal - są poprawne dla motywu podczas gry.

Jednak wynik jest:

Xml wydania:

enter image description here

W Javie:

enter image description here

Ciekawe bit jest, że dzieje się na 21. Na API API 22, oba podejścia dają identyczne wyniki.

Pytanie:

Jestem pewien, że jest to błąd na API 21. Jeśli ktoś może to wyśledzić, możemy prawdopodobnie mnożnik dla wartości alfa/koloru, aby zrównoważyć tę różnicę wizualną.

Oprócz ogólnej dobrej woli, obiecuję również nagrodę, ponieważ już poświęciłem temu trochę czasu.

+0

Jedyna różnica widzę jest to, że poprzez XML ustawić kolor jako odcień 'android:„attr/colorButtonNormal”odcień =' i za pośrednictwem kodu go ustawić jako kolor 'shapeDrawable. getPaint().setColor (color); ' – mikepenz

+0

@mikepenz Yea, argument' color' jest faktycznie uzyskiwany z 'colorButtonNormal '. Wspomniałem o tym wyżej: _Kolejny "kolor" uzyskuje się z 'attr/colorButtonNormal 'tego samego koloru, co w przypadku' android: tint' w definicji xml. – Vikram

+0

Nie, nie o to mi chodzi. Ustawiasz go jako kolor 'shapeDrawable.getPaint(). SetColor (color)' w xml jako 'tint'. dlaczego nie ustawić go jako odcień za pomocą kodu? 'shapeDrawable.setTint();' – mikepenz

Odpowiedz

0

Spróbuj alternatywnego konstruktora new RippleDrawable(ColorStateList.valueOf(colorRipple), backgroundDrawable, null);

Powiązane problemy