2015-01-05 17 views
26

ho il seguente codice per il mio ripple:Come utilizzare RippleDrawable a livello di codice nel codice (non in xml) con Android 5.0 Lollipop?

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

     <shape android:shape="oval"> 
      <solid android:color="?android:colorAccent"/> 
     </shape> 
    </item> 
</ripple> 

Ora voglio dare all'utente la possibilità di scegliere propri colori, quindi ho bisogno di creare il ripple di programmazione.
Ho trovato this e penso che questo sia il modo giusto per farlo, ma non so come gestirlo.

L'ondulazione verrà utilizzato qui:

<ImageButton 
    android:id="@+id/add_button" 
    android:layout_width="@dimen/diameter" 
    android:layout_height="@dimen/diameter" 
    android:layout_gravity="end|bottom" 
    android:layout_marginBottom="@dimen/add_button_margin" 
    android:layout_marginEnd="@dimen/add_button_margin" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentEnd="true" 
    android:src="@drawable/ic_action_add_person" 
    android:tint="@android:color/white" 
    android:background="@drawable/oval_ripple" 
    android:elevation="@dimen/elevation_low" 
    android:stateListAnimator="@anim/button_elevation" 
    android:contentDescription="Neuer Spieler" /> 

ho bisogno di impostare lo sfondo ad un RippleDrawable come questo:

addButton.setBackground(ripple); 
+0

Dove usi la tua risorsa xml? – pskink

+0

@pskink Ho modificato il primo post :) – ich5003

+0

qual è il problema con la creazione di un nuovo 'RippleDrawable'? – pskink

risposta

44

In questo modo sono stato in grado di raggiungere questo obiettivo.

Si noti che questo è Api 21+ solo per cui sarà necessario eseguire il fallback su un normale Drawable se si supportano versioni inferiori.

public static RippleDrawable getPressedColorRippleDrawable(int normalColor, int pressedColor) 
{ 
    return new RippleDrawable(getPressedColorSelector(normalColor, pressedColor), getColorDrawableFromColor(normalColor), null); 
} 

public static ColorStateList getPressedColorSelector(int normalColor, int pressedColor) 
{ 
    return new ColorStateList(
     new int[][] 
      { 
       new int[]{android.R.attr.state_pressed}, 
       new int[]{android.R.attr.state_focused}, 
       new int[]{android.R.attr.state_activated}, 
       new int[]{} 
      }, 
     new int[] 
      { 
       pressedColor, 
       pressedColor, 
       pressedColor, 
       normalColor 
      } 
    ); 
} 

public static ColorDrawable getColorDrawableFromColor(int color) 
{ 
    return new ColorDrawable(color); 
} 

Edit: Ho armeggiato con questo un po 'di più e ha scoperto che il ColorStateList non ha bisogno di essere quasi così complesso come la soluzione di cui sopra. L'ho semplificato per il frammento di seguito. (Tutto il resto nel blocco di codice sopra è lo stesso. Ho solo modificato la creazione di ColorStateList.) Lascerò il blocco precedente come originale, nel caso in cui questo metodo non funzioni per qualcuno.

new ColorStateList(
    new int[][] 
     { 
      new int[]{} 
     }, 
    new int[] 
     { 
      pressedColor 
     } 
); 
+5

Grazie mille per la tua risposta :) (Non posso darti un upvote, non abbastanza reputazioni). – ich5003

+0

Sicuro; è stato un dolore capire così sono felice di condividere. :) Ha funzionato per te? Ci ho lavorato ancora un po 'e ho imparato che avrei potuto semplificare notevolmente la ColorStateList e ottenere lo stesso risultato, quindi ho modificato la mia risposta per includerla. – kdenney

+9

Puoi anche farlo usando 'ColorStateList.valueOf (rippleColor);' – milosmns

19
public static Drawable getAdaptiveRippleDrawable(
    int normalColor, int pressedColor) { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
     return new RippleDrawable(ColorStateList.valueOf(pressedColor), 
       null, getRippleMask(normalColor)); 
    } else { 
     return getStateListDrawable(normalColor, pressedColor); 
    } 
} 

private static Drawable getRippleMask(int color) { 
    float[] outerRadii = new float[8]; 
    // 3 is radius of final ripple, 
    // instead of 3 you can give required final radius 
    Arrays.fill(outerRadii, 3); 

    RoundRectShape r = new RoundRectShape(outerRadii, null, null); 
    ShapeDrawable shapeDrawable = new ShapeDrawable(r); 
    shapeDrawable.getPaint().setColor(color); 
    return shapeDrawable; 
} 

public static StateListDrawable getStateListDrawable(
    int normalColor, int pressedColor) { 
    StateListDrawable states = new StateListDrawable(); 
    states.addState(new int[]{android.R.attr.state_pressed}, 
     new ColorDrawable(pressedColor)); 
    states.addState(new int[]{android.R.attr.state_focused}, 
     new ColorDrawable(pressedColor)); 
    states.addState(new int[]{android.R.attr.state_activated}, 
     new ColorDrawable(pressedColor)); 
    states.addState(new int[]{}, 
     new ColorDrawable(normalColor)); 
    return states; 
} 

è possibile ottenere il drawable e si applicano a qualsiasi vista utilizzando view.setDrawable.
Per i dispositivi Lollipop + si otterrà un ripple altrimenti cambierà il colore della vista.

+0

Questo è bello. Un inconveniente, penso, è che potrebbe perdere gli angoli arrotondati quando applicato su un dispositivo pre-lecca-lecca, perché 'ColorDrawable's in' StateListDrawable' non ha forma. Potremmo fornire 'ShapeDrawable 'colorato invece di mantenere la forma. Ma forse questo inizierebbe a diventare un po 'pesante.In questo caso, l'ennesima soluzione sarebbe quella di creare un "ColorStateDrawable" personalizzato con un metodo "setColor" che eviti di ristestare tutti gli oggetti necessari per uno StateListDrawable. – John

+0

Trovato qualcosa di simile qui: https://github.com/gabrielemariotti/colorpickercollection/blob/master/ColorPicker/src/it/gmariotti/android/example/colorpicker/calendarstock/ColorStateDrawable.java – John

2

Fondamentalmente, è necessario creare un nuovo oggetto RippleDrawable. Per i dispositivi pre-Lollipop, si desidera uno StateListDrawable (come già suggerito da altri). Ho scritto un GIST un po 'pieno di risorse con una serie di utili metodi relativi a Drawables e colorazione: https://gist.github.com/milosmns/6566ca9e3b756d922aa5

Molto probabilmente vorrete usare #getBackgroundDrawable() da quel singleton.

Problemi correlati