Kształty wielowarstwowe
Chciałbym stworzyć kształt podobny do poniższego obrazka:
Zwróć uwagę, że górna połowa gradientu gradientu od koloru 1 do koloru 2, ale jest dolna połowa, która gradientu od koloru 3 do koloru 4. Wiem, jak zrobić kształt z jednym gradientem, ale nie jestem pewien, jak podzielić kształt na dwie połówki i zrobić 1 kształt z 2 różnymi gradientami.
Jakieś pomysły?
5 answers
Myślę, że nie da się tego zrobić w XML( przynajmniej Nie w Androidzie), ale znalazłem dobre rozwiązanie opublikowane tutaj , które wygląda na to, że byłoby to bardzo pomocne!
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);
Zasadniczo, tablica int pozwala na wybranie wielu zatrzymań kolorów, a następująca tablica float określa, gdzie są one umieszczone (od 0 do 1). Można wtedy, jak podano, po prostu użyć tego jako standardowego Drawable.
Edit: oto jak możesz tego użyć w swoim scenariuszu. Powiedzmy, że masz guzik. zdefiniowane w XML tak:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
W metodzie onCreate() umieściłbyś coś takiego:
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);
Nie mogę tego w tej chwili przetestować, to jest kod z mojej głowy, ale w zasadzie wystarczy wymienić, lub dodać przystanki dla kolorów, których potrzebujesz. Zasadniczo, w moim przykładzie, można zacząć od jasnozielonego, blaknięcie do bieli nieco przed środkiem (aby dać blaknięcie, a nie ostre przejście), blaknięcie od bieli do średniej zieleni między 45% i 55%, a następnie blaknięcie od średniej zieleni do ciemności Zielony od 55% do końca. Może to nie wygląda dokładnie tak jak twój kształt (w tej chwili nie mam możliwości testowania tych kolorów), ale możesz zmodyfikować to, aby odtworzyć swój przykład.
Edit: również 0, 0, 0, theButton.getHeight()
odnosi się do współrzędnych x0, y0, x1, y1 gradientu. W zasadzie zaczyna się od x = 0( lewa strona), y = 0 (góra) i rozciąga się do x = 0 (chcemy pionowego gradientu, więc nie jest potrzebny kąt od lewej do prawej), y = wysokość przycisku. Więc gradient idzie pod kątem 90 stopni od góry przycisku do dołu przycisku.
Edit: Ok, więc mam jeszcze jeden pomysł, który działa, haha. W tej chwili działa w XML, ale powinien być wykonalny również dla kształtów w Javie. To trochę skomplikowane i wyobrażam sobie, że istnieje sposób, aby uprościć go do jednego kształtu, ale to jest to, co mam do teraz:
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>
Okej, więc w zasadzie stworzyłem gradient kształtu w XML dla poziomego Zielonego gradientu, ustawionego pod kątem 0 stopni, przechodzącego od lewego zielonego koloru górnego obszaru do prawego zielonego koloru. Następnie wykonałam kształt prostokąta z połową przezroczystej szarości. Jestem pewien, że to może być wplecione w layer-list XML, ale nie wiem jak. Ale OK, wtedy rodzaj hacky część wchodzi w pliku XML layer_list. Kładę zielony gradient jako dolną warstwę, a następnie nakładkę pół jako drugą warstwę, przesuniętą od góry o 50dp. Oczywiście chciałbyś, aby ta liczba zawsze była o połowę mniejsza niż rozmiar widoku, a nie stała 50dp. Nie sądzę jednak, że możesz użyć procentów. Stamtąd właśnie wstawiłem TextView do mojego testu.xml layout, używając layer_list.plik xml jako moje tło. Ustawiłem wysokość na 100dp( dwa razy większy od przesunięcia nakładki), co daje:
Tada!Jeszcze jedna edycja: zdałem sobie sprawę, że możesz po prostu osadzić kształty na liście warstw rysowanych jako elementy, co oznacza, że nie potrzebujesz już 3 oddzielnych plików XML! Można osiągnąć ten sam wynik łącząc je w ten sposób:
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>
Możesz warstwy tyle przedmiotów, jak chcesz w ten sposób! Może spróbuję się pobawić i zobaczyć, czy Mogę uzyskać bardziej wszechstronny wynik poprzez Javę.
To chyba ostatnia edycja...: ok, więc zdecydowanie możesz naprawić pozycjonowanie poprzez Javę, jak poniżej:
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);
Jednak! Prowadzi to do kolejnego irytującego problemu, ponieważ nie można zmierzyć widoku tekstu, dopóki nie zostanie on narysowany. Nie jestem jeszcze pewien, jak możesz to osiągnąć...ale ręczne wstawianie numeru dla topInset działa.
I lied, one more edit
Ok, dowiedzieliśmy się jak ręcznie zaktualizować tę warstwę, aby dopasować ją do wysokości kontenera, pełny opis można znaleźć tutaj . Ten kod powinien zostać użyty w metodzie onCreate ():
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);
}
});
I skończyłem! Whew! :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-15 18:20:59
Można warstwować kształty gradientu w xml za pomocą listy warstw. Wyobraź sobie przycisk ze stanem domyślnym jak poniżej, gdzie drugi element jest półprzezroczysty. Dodaje coś w rodzaju winietowania. (Proszę wybaczyć niestandardowe kolory.)
<!-- Normal state. -->
<item>
<layer-list>
<item>
<shape>
<gradient
android:startColor="@color/grey_light"
android:endColor="@color/grey_dark"
android:type="linear"
android:angle="270"
android:centerColor="@color/grey_mediumtodark" />
<stroke
android:width="1dp"
android:color="@color/grey_dark" />
<corners
android:radius="5dp" />
</shape>
</item>
<item>
<shape>
<gradient
android:startColor="#00666666"
android:endColor="#77666666"
android:type="radial"
android:gradientRadius="200"
android:centerColor="#00666666"
android:centerX="0.5"
android:centerY="0" />
<stroke
android:width="1dp"
android:color="@color/grey_dark" />
<corners
android:radius="5dp" />
</shape>
</item>
</layer-list>
</item>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-12 15:29:53
Możesz to zrobić używając tylko kształtów xml - wystarczy użyć layer-list i negative padding w następujący sposób:
<layer-list>
<item>
<shape>
<solid android:color="#ffffff" />
<padding android:top="20dp" />
</shape>
</item>
<item>
<shape>
<gradient android:endColor="#ffffff" android:startColor="#efefef" android:type="linear" android:angle="90" />
<padding android:top="-20dp" />
</shape>
</item>
</layer-list>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-24 13:32:07
Czy próbowałeś nałożyć jeden gradient z prawie przezroczystym kryciem dla podświetlenia na inny obraz z nieprzezroczystym kryciem dla zielonego gradientu?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-07 20:12:33
Wypróbuj tę metodę, a potem możesz zrobić wszystko, co chcesz.
To jest jak stos więc uważaj, który element jest pierwszy lub ostatni.
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="50dp" android:start="10dp" android:left="10dp">
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="3dp" />
<solid android:color="#012d08"/>
</shape>
</item>
<item android:top="50dp">
<shape android:shape="rectangle">
<solid android:color="#7c4b4b" />
</shape>
</item>
<item android:top="90dp" android:end="60dp">
<shape android:shape="rectangle">
<solid android:color="#e2cc2626" />
</shape>
</item>
<item android:start="50dp" android:bottom="20dp" android:top="120dp">
<shape android:shape="rectangle">
<solid android:color="#360e0e" />
</shape>
</item>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-02 17:08:11