Ich glaube nicht, dass Sie dies in XML tun können (zumindest nicht in Android), aber ich habe hier eine gute Lösung gefunden , die anscheinend eine große Hilfe wäre!
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, width, height,
new int[]{Color.GREEN, Color.GREEN, Color.WHITE, Color.WHITE},
new float[]{0,0.5f,.55f,1}, Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p=new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
Grundsätzlich können Sie mit dem Int-Array mehrere Farbstopps auswählen. Das folgende Float-Array definiert, wo diese Stopps positioniert sind (von 0 bis 1). Sie können dies dann, wie angegeben, einfach als Standard-Drawable verwenden.
Bearbeiten: So können Sie dies in Ihrem Szenario verwenden. Angenommen, Sie haben eine Schaltfläche in XML wie folgt definiert:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
Sie würden dann so etwas in Ihre onCreate () -Methode einfügen:
Button theButton = (Button)findViewById(R.id.thebutton);
ShapeDrawable.ShaderFactory sf = new ShapeDrawable.ShaderFactory() {
@Override
public Shader resize(int width, int height) {
LinearGradient lg = new LinearGradient(0, 0, 0, theButton.getHeight(),
new int[] {
Color.LIGHT_GREEN,
Color.WHITE,
Color.MID_GREEN,
Color.DARK_GREEN }, //substitute the correct colors for these
new float[] {
0, 0.45f, 0.55f, 1 },
Shader.TileMode.REPEAT);
return lg;
}
};
PaintDrawable p = new PaintDrawable();
p.setShape(new RectShape());
p.setShaderFactory(sf);
theButton.setBackground((Drawable)p);
Ich kann dies im Moment nicht testen, dies ist Code aus meinem Kopf, aber im Grunde nur ersetzen oder Stopps für die Farben hinzufügen, die Sie benötigen. Grundsätzlich würden Sie in meinem Beispiel mit einem Hellgrün beginnen, kurz vor der Mitte zu Weiß verblassen (um eine Überblendung anstelle eines harten Übergangs zu erzielen), zwischen 45% und 55% von Weiß zu Mittelgrün überblenden und dann abblenden mittelgrün bis dunkelgrün von 55% bis zum Ende. Dies sieht möglicherweise nicht genau wie Ihre Form aus (im Moment habe ich keine Möglichkeit, diese Farben zu testen), aber Sie können dies ändern, um Ihr Beispiel zu replizieren.
Bearbeiten: Das 0, 0, 0, theButton.getHeight()
bezieht sich auch auf die x0-, y0-, x1- und y1-Koordinaten des Gradienten. Im Grunde genommen beginnt es bei x = 0 (linke Seite), y = 0 (oben) und erstreckt sich bis x = 0 (wir wollen einen vertikalen Gradienten, daher ist kein Winkel von links nach rechts erforderlich), y = Höhe der Taste. Der Farbverlauf verläuft also in einem Winkel von 90 Grad von der Oberseite der Schaltfläche zur Unterseite der Schaltfläche.
Edit: Okay, also ich habe noch eine Idee, die funktioniert, haha. Im Moment funktioniert es in XML, sollte aber auch für Formen in Java möglich sein. Es ist ziemlich komplex und ich stelle mir vor, dass es eine Möglichkeit gibt, es in eine einzige Form zu vereinfachen, aber das habe ich jetzt:
green_horizontal_gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners
android:radius="3dp"
/>
<gradient
android:angle="0"
android:startColor="#FF63a34a"
android:endColor="#FF477b36"
android:type="linear"
/>
</shape>
half_overlay.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid
android:color="#40000000"
/>
</shape>
layer_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item
android:drawable="@drawable/green_horizontal_gradient"
android:id="@+id/green_gradient"
/>
<item
android:drawable="@drawable/half_overlay"
android:id="@+id/half_overlay"
android:top="50dp"
/>
</layer-list>
test.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
>
<TextView
android:id="@+id/image_test"
android:background="@drawable/layer_list"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center"
android:text="Layer List Drawable!"
android:textColor="@android:color/white"
android:textStyle="bold"
android:textSize="26sp"
/>
</RelativeLayout>
Okay, im Grunde habe ich in XML einen Formverlauf für den horizontalen grünen Farbverlauf erstellt, der in einem Winkel von 0 Grad von der linken grünen Farbe des oberen Bereichs zur rechten grünen Farbe festgelegt ist. Als nächstes machte ich ein Formrechteck mit einem halbtransparenten Grau. Ich bin mir ziemlich sicher, dass dies in das XML der Ebenenliste eingefügt werden könnte, wodurch diese zusätzliche Datei vermieden wird, aber ich bin mir nicht sicher, wie. Aber okay, dann kommt die Art von Hacky-Teil in die XML-Datei layer_list. Ich habe den grünen Farbverlauf als untere Ebene und dann die halbe Überlagerung als zweite Ebene eingefügt, die um 50 dp von der Oberseite versetzt ist. Natürlich möchten Sie, dass diese Zahl immer die Hälfte Ihrer Ansichtsgröße beträgt und keine festen 50 dp. Ich glaube jedoch nicht, dass Sie Prozentsätze verwenden können. Von dort aus habe ich gerade eine Textansicht in mein test.xml-Layout eingefügt und dabei die Datei layer_list.xml als Hintergrund verwendet.
Tada!
Noch eine Bearbeitung : Ich habe festgestellt, dass Sie die Formen einfach in die als Elemente zeichnbare Ebenenliste einbetten können, sodass Sie keine 3 separaten XML-Dateien mehr benötigen! Sie können das gleiche Ergebnis erzielen, indem Sie sie wie folgt kombinieren:
layer_list.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android"
>
<item>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<corners
android:radius="3dp"
/>
<gradient
android:angle="0"
android:startColor="#FF63a34a"
android:endColor="#FF477b36"
android:type="linear"
/>
</shape>
</item>
<item
android:top="50dp"
>
<shape
android:shape="rectangle"
>
<solid
android:color="#40000000"
/>
</shape>
</item>
</layer-list>
Auf diese Weise können Sie so viele Elemente überlagern, wie Sie möchten! Ich kann versuchen, herumzuspielen und zu sehen, ob ich mit Java ein vielseitigeres Ergebnis erzielen kann.
Ich denke, dies ist die letzte Bearbeitung ... : Okay, Sie können die Positionierung also definitiv über Java korrigieren, wie folgt:
TextView tv = (TextView)findViewById(R.id.image_test);
LayerDrawable ld = (LayerDrawable)tv.getBackground();
int topInset = tv.getHeight() / 2 ; //does not work!
ld.setLayerInset(1, 0, topInset, 0, 0);
tv.setBackgroundDrawable(ld);
Jedoch! Dies führt zu einem weiteren ärgerlichen Problem, da Sie die Textansicht erst nach dem Zeichnen messen können. Ich bin mir noch nicht ganz sicher, wie Sie dies erreichen können ... aber das manuelle Einfügen einer Nummer für topInset funktioniert.
Ich habe gelogen, noch eine Bearbeitung
Okay, Sie haben herausgefunden, wie Sie diese Ebene manuell aktualisieren können, um sie an die Höhe des Containers anzupassen. Eine vollständige Beschreibung finden Sie hier . Dieser Code sollte in Ihrer onCreate () -Methode enthalten sein:
final TextView tv = (TextView)findViewById(R.id.image_test);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
LayerDrawable ld = (LayerDrawable)tv.getBackground();
ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
}
});
Und ich bin fertig! Wütend! :) :)