2014-12-01 5 views

Antwort

7

Zuerst müssen Sie das Zeichen aus der Ansicht abrufen.

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

} 

Methode setHotspot(x,y); wird verwendet, um festgelegt, wo die Welligkeit Animation starten, sonst, wenn nicht gesetzt ist, nehmen die RippleDrawable die Rect, wo es sich befindet (dh die Rect der Ansicht, wo es als Hintergrund festgelegt ist) und wird den Welleneffekt von der Mitte aus beginnen.

setVisible(true, true) macht das Zeichen sichtbar und das letzte Argument wird die Animation unabhängig vom aktuellen Zeichenstatus erzwingen.

+0

Nizza. Funktioniert die Animation wie ein Klick oder ein langer Klick (dh die Auswahl bleibt erhalten)? –

+0

Sie sollten versuchen, Zeichenstatus programmgesteuert festzulegen. Wie: 'int [] state = new int [] {android.R.attr.state_pressed}' und 'ripple.setState (state);'. Ich habe nicht getestet, ob Sie es mit 'setVisible (true, true)' verbinden sollten. Weil das Zeichenprogramm bei Zustandsänderungen automatisch aktualisiert/animiert wird. –

+0

Ich verstehe nicht. Können Sie bitte ein Beispiel für beide Verhaltensweisen posten? –

23

Ja, gibt es! Um programmgesteuert eine Ripple auszulösen, müssen Sie den Zustand RippleDrawable mit setState() setzen. Aufruf setVisible() tut NICHT arbeiten!


Die Lösung

die Welligkeit zeigen Ihnen den Zustand versetzen müssen gleichzeitig gedrückt und aktiviert:

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

Die Welligkeit wird so lange gezeigt werden, wie die Staaten sind einstellen. Wenn Sie die Welligkeit wieder ausblenden möchten setzen Sie den Zustand in einen leeren int[]:

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

Sie den Punkt, von dem Set kann die Welligkeit ausgeht setHotspot() durch den Aufruf.


Wie es

arbeitet Ich habe viel debuggt und studierte den Quellcode RippleDrawable auf und ab, bis ich, dass die Welligkeit realisiert wird, in onStateChange() tatsächlich ausgelöst. Der Aufruf setVisible() hat keine Wirkung und bewirkt nie, dass tatsächlich eine Welligkeit auftritt.

Der relevante Teil des Quellcodes von RippleDrawable ist dies:

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

Wie Sie beide sehen können, wenn das Attribut aktiviert und gedrückt eingestellt sind beide dann die Welligkeit und Hintergrund wird aktiviert und die Welligkeit sein angezeigt. Solange der fokussierte Zustand eingestellt ist, wird zusätzlich der Hintergrund aktiviert. Damit können Sie die Welligkeit auslösen und den Hintergrund unabhängig von der Farbe wechseln lassen. Wenn Sie interessiert sind, können Sie den gesamten Quellcode von RippleDrawablehere einsehen.

11

I eingebaut/kombiniert, um die Antworten von @Xaver Kapeller und @Nikola Despotoski oben:

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

programmatisch eine sich allmählich ausbreitende Wirkung auf Befehl erzwingen, rufen einfach forceRippleAnimation(), vorbei an der Ansicht, die Sie als kräuseln wollen ein Parameter

+0

Änderung an if (Build.VERSION.SDK_INT> = 21 && Hintergrundinstanz von RippleDrawable), wegen Absturz auf Android <21 – iscariot

+0

@iscariot. Guter Ruf. Habe es einfach geändert. – Luke

+0

Um den Status auf aktuelle Werte zurückzusetzen, rufen Sie 'rippleDrawable.setState (view.getDrawableState())' 'auf, anstatt leere Statusgruppen zu erzwingen. –

5

Hier ist die Kombination von Nikola setHotSpot() und 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); 
} 
Verwandte Themen