2017-01-09 1 views
0

Ich mache eine benutzerdefinierte Schaltflächenansicht mit einem Farbverlauf, abgerundeten Ecken und einem transparenten Hintergrund. Ich bin der Hintergrund der Schaltfläche zum ziehbar durch den folgenden Code generiert Einstellung:Ripple-Effekt bei transparenter benutzerdefinierter Schaltflächenansicht

protected Drawable getBackgroundDrawable() { 
    GradientDrawable backgroundDrawable = new GradientDrawable(
      mOrientation, 
      mGradientColors); 
    backgroundDrawable.setCornerRadius(getHeight()/2); 
    backgroundDrawable.setShape(GradientDrawable.RECTANGLE); 

    if (!mFilled) { 
     Bitmap background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); 
     Canvas backgroundCanvas = new Canvas(background); 
     backgroundCanvas.drawARGB(0, 0, 0, 0); 
     backgroundDrawable.setBounds(0, 0, getWidth(), getHeight()); 
     backgroundDrawable.draw(backgroundCanvas); 

     Paint rectPaint = new Paint(); 
     rectPaint.setAntiAlias(true); 
     rectPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 
     backgroundCanvas.drawRoundRect(new RectF(mStroke, mStroke, 
         getWidth() - mStroke, 
         getHeight() - mStroke), 
       getHeight()/2, 
       getHeight()/2, 
       rectPaint); 

     return new BitmapDrawable(getResources(), background); 
    } else { 
     return backgroundDrawable; 
    } 
} 

Das einzige Problem ist, wenn Sie die Taste jetzt klicken, haben Sie kein Feedback. Wie kann ich einen Ripple-Effekt auf der Rückseite der Schaltfläche hinzufügen, wenn ich den generierten Drawable bereits als Hintergrund verwende? Muss ich etwas mit einem LayerDrawable machen?

Meine Schaltfläche sieht wie folgt aus:

enter image description here

Was ich wirklich

erstellen Drawable programmatisch erreichen wollen, dass das gleiche Ergebnis wie dieses XML ziehbar hat, wo das Element in der Ripple-Element ist mein generiert Drawable im Bild oben:

<ripple android:color="@android:color/black" xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/background"></item> 
</ripple> 

Ich habe versucht

Ich habe jetzt versucht, ein RippleDrawable in Kombination mit einem GradientDrawable zu erstellen, um das XML oben in Code neu zu erstellen. Sehr einfach, dachte ich:

GradientDrawable gradientDrawable = new GradientDrawable(); 
gradientDrawable.setColor(Color.TRANSPARENT); 
gradientDrawable.setStroke(mStroke, Color.GREEN); 
gradientDrawable.setCornerRadius(getHeight()/2); 

ColorStateList rippleStateList = ColorStateList.valueOf(Color.BLUE); 
return new RippleDrawable(rippleStateList, gradientDrawable, gradientDrawable); 

Dies gibt ein einfaches Zeichen mit einem grünen Strich zurück. Wenn Sie darauf klicken, passiert jedoch nichts. Im Gegensatz zum XML, wo Sie deutlich einen Welleneffekt über der Grenze sehen können. Wenn ich den dritten Parameter auf null, denselben Effekt einstelle. Wenn ich nur den zweiten Parameter auf null einstelle, gibt es nur ein leeres Transparent zurück, das ohne Welleneffekte gezeichnet werden kann.

+1

In der Schaltfläche XML haben Sie versucht 'android: Vordergrund ="? Android: attr/selectableItemBackground "' –

+1

Das funktioniert, ein Schritt näher an die Lösung. Einziges Problem, die Welligkeit ignoriert die abgerundeten Ecken. –

+0

Das liegt daran, dass die Welligkeit an die Grenzen des Knopfes selbst geht, nicht sicher, aber gibt es eine Möglichkeit, die Grenzen an den äußeren Rand des Gradientenzuges zu koppeln? –

Antwort

2

Sie sollten eine RippleDrawable als Hintergrund Ihrer benutzerdefinierten Schaltfläche verwenden. Die RippleDrawable hat eine Maskenschicht, die Sie suchen. Gehen Sie programmatisch diesem können Sie ein RippleDrawable wie so erstellen:

float[] outerRadii = new float[8]; 
Arrays.fill(outerRadii, height/2); 

RoundRectShape shape = new RoundRectShape(outerRadii, null, null); 
ShapeDrawable mask = new ShapeDrawable(shape); 

ColorStateList stateList = ColorStateList.valueof(ContextCompat.getColor(getContext(), R.color.ripple)); 

setBackground(new RippleDrawable(stateList, getBackgroundDrawable(), mask); 

Beachten Sie, dass RippleDrawable für API-Ebene nur verfügbar ist, 21+, also, wenn Sie schauen, um ältere Versionen zu unterstützen auch müssen Sie fallen zurück zu etwas anderem; möglicherweise android.R.attr.selectableItemBackground oder StateListDrawable, die Ihrem Knopf einen grundlegenden "gepressten" Hintergrund für ältere Plattformversionen geben werden.

+0

Diese Antwort ist besser als meine Kommentare - sollte als richtige Antwort angenommen werden –

+0

Ich denke, was ich will, werde ich es bald überprüfen! Vielen Dank! –

+0

Wenn ich diese Ripple benutze, ist das nur ein transparenter Zeichensatz und nichts passiert, wenn du es drückst. Ich kann nicht herausfinden, wie das RippleDrawable funktioniert. –

Verwandte Themen