2014-12-01 9 views

Odpowiedz

7

Najpierw należy pobrać wyciąg z widoku.

private void forceRippleAnimation(View v, float x, float y){ 
    Drawable background = v.getBackground(); 
    if(background instanceof RippleDrawable){ 
    RippleDrawable ripple = (RippleDrawable)background; 
    ripple.setHotspot(x, y); 
    ripple.setVisible (true, true); 
    } 

} 

Metoda setHotspot(x,y); służy do ustawiania skąd tętnienia animacja rozpocznie, w przeciwnym razie, jeśli nie jest ustawiona, RippleDrawable zajmie Rect gdzie rezyduje (tj Rect od widoku, w którym jest on ustawiony jako tło) i zacznie efekt tętnienia od centrum.

setVisible(true, true) spowoduje, że losowanie będzie widoczne, a ostatni argument wymusi animację bez względu na bieżący stan losowania.

+0

Nicea. Czy animacja działa jak kliknięcie lub długie kliknięcie (co oznacza, że ​​zaznaczenie pozostanie)? –

+0

Powinieneś spróbować programowo ustawić stan rysowania. Podobnie jak: 'int [] state = new int [] {android.R.attr.state_pressed}' i 'ripple.setState (state);'. Nie testowałem, jeśli powinieneś połączyć go z 'setVisible (true, true)'. Ponieważ losowanie jest automatycznie aktualizowane/animowane po zmianach stanu. –

+0

Nie rozumiem. Czy możesz wysłać próbkę dla obu zachowań? –

23

Tak, jest! Aby aktywować programowanie, należy ustawić stan urządzenia RippleDrawable na setState(). Dzwonienie pod numer setVisible() robi NOT działa!


Rozwiązanie

Aby pokazać tętnienia trzeba ustawić stan na prasowane i włączone w tym samym czasie:

rippleDrawable.setState(new int[] { android.R.attr.state_pressed, android.R.attr.state_enabled }); 

tętnienia zostaną pokazane tak długo jak te stany są zestaw. Gdy chcesz ukryć tętnienia ponownie ustawić stan do pustej int[]:

rippleDrawable.setState(new int[] { }); 

Można ustawić punkt, z którego szmer rozchodzący wywołując setHotspot().


Jak to działa

Mam debugowany dużo studiował kodu źródłowego RippleDrawable w górę iw dół, aż zdałem sobie sprawę, że tętnienia jest rzeczywiście wywołane w onStateChange(). Wywołanie setVisible() nie daje żadnego efektu i nigdy nie powoduje pojawiania się żadnych zmarszczek.

Odpowiedni fragment kodu źródłowego RippleDrawable to:

@Override 
protected boolean onStateChange(int[] stateSet) { 
    final boolean changed = super.onStateChange(stateSet); 

    boolean enabled = false; 
    boolean pressed = false; 
    boolean focused = false; 

    for (int state : stateSet) { 
     if (state == R.attr.state_enabled) { 
      enabled = true; 
     } 
     if (state == R.attr.state_focused) { 
      focused = true; 
     } 
     if (state == R.attr.state_pressed) { 
      pressed = true; 
     } 
    } 

    setRippleActive(enabled && pressed); 
    setBackgroundActive(focused || (enabled && pressed)); 

    return changed; 
} 

Jak widać, jeśli oba włączone i przycisnął atrybut jest ustawiony to zarówno tętnienia i tło zostanie aktywowane i tętnienia będzie wystawiany. Dodatkowo tak długo, jak ustawiasz stan skupienia, tło również zostanie aktywowane. Dzięki temu możesz wywołać falowanie i niezależnie zmienić kolor tła.

Jeśli jesteś zainteresowany, możesz wyświetlić cały kod źródłowy RippleDrawablehere.

11

I włączone/połączono odpowiedzi od @Xaver Kapeller i @Nikola Despotoski powyżej:

protected void forceRippleAnimation(View view) 
{ 
    Drawable background = view.getBackground(); 

    if(Build.VERSION.SDK_INT >= 21 && background instanceof RippleDrawable) 
    { 
     final RippleDrawable rippleDrawable = (RippleDrawable) background; 

     rippleDrawable.setState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled}); 

     Handler handler = new Handler(); 

     handler.postDelayed(new Runnable() 
     { 
      @Override public void run() 
      { 
       rippleDrawable.setState(new int[]{}); 
      } 
     }, 200); 
    } 
} 

programowo wymusić odzew na komendę, po prostu zadzwoń forceRippleAnimation(), przekazując widok, który chcesz marszczyć jak parametr.

+0

zmienić na jeśli (Build.VERSION.SDK_INT> = 21 && instancja tła RippleDrawable), z powodu awarii na Androida <21 – iscariot

+0

@iscariot. Dobra decyzja. Po prostu to zmieniono. – Luke

+0

Aby zresetować stan do bieżących wartości, wywołaj 'rippleDrawable.setState (view.getDrawableState())' zamiast wymuszania pustego zestawu stanów. –

5

Oto kombinacja Nikola setHotSpot() i https://stackoverflow.com/a/25415471/1474113

private void forceRipple(View view, int x, int y) { 
    Drawable background = view.getBackground(); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && background instanceof RippleDrawable) { 
     background.setHotspot(x, y); 
    } 
    view.setPressed(true); 
    // For a quick ripple, you can immediately set false. 
    view.setPressed(false); 
} 
Powiązane problemy