Tôi không nghĩ bạn có thể làm điều này bằng XML (ít nhất là không phải trong Android), nhưng tôi đã tìm thấy một giải pháp tốt được đăng ở đây có vẻ như nó sẽ là một trợ giúp tuyệt vời!
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);
Về cơ bản, mảng int cho phép bạn chọn nhiều điểm dừng màu và mảng float sau xác định vị trí các điểm dừng đó (từ 0 đến 1). Sau đó, bạn có thể, như đã nêu, chỉ cần sử dụng điều này như một Drawable tiêu chuẩn.
Chỉnh sửa: Đây là cách bạn có thể sử dụng điều này trong kịch bản của bạn. Giả sử bạn có một Nút được định nghĩa bằng XML như vậy:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
Sau đó, bạn sẽ đặt một cái gì đó như thế này vào phương thức onCreate () của bạn:
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);
Tôi không thể kiểm tra điều này vào lúc này, đây là mã từ đầu của tôi, nhưng về cơ bản chỉ cần thay thế hoặc thêm điểm dừng cho các màu mà bạn cần. Về cơ bản, trong ví dụ của tôi, bạn sẽ bắt đầu với màu lục nhạt, nhạt dần sang màu trắng trước trung tâm (để làm mờ dần, thay vì chuyển đổi khắc nghiệt), mờ dần từ trắng sang giữa xanh giữa 45% và 55%, sau đó mờ dần từ giữa xanh đến xanh đậm từ 55% đến cuối. Điều này có thể trông không giống hệt hình dạng của bạn (Ngay bây giờ, tôi không có cách nào để kiểm tra các màu này), nhưng bạn có thể sửa đổi điều này để sao chép ví dụ của mình.
Chỉnh sửa: Ngoài ra, tham chiếu 0, 0, 0, theButton.getHeight()
đến tọa độ x0, y0, x1, y1 của gradient. Vì vậy, về cơ bản, nó bắt đầu ở x = 0 (bên trái), y = 0 (trên cùng) và kéo dài đến x = 0 (chúng tôi muốn có độ dốc dọc, do đó không cần góc trái sang phải), y = chiều cao của nút. Vì vậy, độ dốc đi ở một góc 90 độ từ đỉnh nút đến dưới cùng của nút.
Chỉnh sửa: Được rồi, vì vậy tôi có thêm một ý tưởng hoạt động, haha. Ngay bây giờ, nó hoạt động trong XML, nhưng cũng có thể thực hiện được cho các hình dạng trong Java. Nó khá phức tạp và tôi tưởng tượng có một cách để đơn giản hóa nó thành một hình dạng duy nhất, nhưng đây là những gì tôi có bây giờ:
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>
Được rồi, về cơ bản, tôi đã tạo một gradient hình dạng trong XML cho gradient xanh lục ngang, được đặt ở góc 0 độ, đi từ màu xanh lục bên trái của khu vực trên cùng, sang màu xanh lục bên phải. Tiếp theo, tôi tạo một hình chữ nhật với một nửa màu xám trong suốt. Tôi khá chắc chắn rằng có thể được đưa vào XML trong danh sách lớp, làm mờ tệp bổ sung này, nhưng tôi không biết làm thế nào. Nhưng không sao, sau đó loại phần hacky xuất hiện trong tệp XML layer_list. Tôi đặt gradient màu xanh lá cây làm lớp dưới cùng, sau đó đặt lớp phủ một nửa làm lớp thứ hai, bù lại từ trên xuống 50dp. Tuy nhiên, rõ ràng bạn muốn con số này luôn bằng một nửa dù kích thước chế độ xem của bạn là bao nhiêu và không phải là 50dp cố định. Tôi không nghĩ rằng bạn có thể sử dụng tỷ lệ phần trăm, mặc dù. Từ đó, tôi chỉ cần chèn một TextView vào bố cục test.xml của mình, sử dụng tệp layer_list.xml làm nền.
Tada!
Thêm một chỉnh sửa : Tôi đã nhận ra rằng bạn chỉ có thể nhúng các hình dạng vào danh sách lớp có thể vẽ dưới dạng các mục, nghĩa là bạn không cần 3 tệp XML riêng biệt nữa! Bạn có thể đạt được kết quả tương tự khi kết hợp chúng như vậy:
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>
Bạn có thể layer nhiều mặt hàng như bạn muốn theo cách này! Tôi có thể thử chơi xung quanh và xem liệu tôi có thể có được kết quả linh hoạt hơn thông qua Java không.
Tôi nghĩ rằng đây là lần chỉnh sửa cuối cùng ... : Được rồi, vì vậy bạn chắc chắn có thể sửa lỗi định vị thông qua Java, như sau:
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);
Tuy nhiên! Điều này dẫn đến một vấn đề khó chịu khác là bạn không thể đo TextView cho đến khi nó được rút ra. Tôi không chắc chắn làm thế nào bạn có thể thực hiện điều này ... nhưng chèn thủ công một số cho topInset không hoạt động.
Tôi nói dối, thêm một lần chỉnh sửa
Được rồi, tìm ra cách cập nhật thủ công lớp này có thể vẽ được để phù hợp với chiều cao của container, mô tả đầy đủ có thể được tìm thấy ở đây . Mã này sẽ đi theo phương thức onCreate () của bạn:
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);
}
});
Và tôi đã hoàn thành! Phù! :)