ฉันไม่คิดว่าคุณสามารถทำได้ใน XML (อย่างน้อยไม่ได้อยู่ใน Android) แต่ฉันพบวิธีแก้ปัญหาที่ดีที่โพสต์ที่นี่ซึ่งดูเหมือนว่ามันจะช่วยได้มาก!
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);
โดยทั่วไปแล้วอาร์เรย์ int ช่วยให้คุณสามารถเลือกหยุดสีหลายสีและอาร์เรย์ลอยดังต่อไปนี้กำหนดตำแหน่งที่หยุดเหล่านั้น (จาก 0 ถึง 1) จากนั้นคุณสามารถใช้สิ่งนี้เป็น Drawable มาตรฐานได้
แก้ไข: นี่คือวิธีที่คุณสามารถใช้สิ่งนี้ในสถานการณ์ของคุณ สมมติว่าคุณมีปุ่มที่กำหนดไว้ใน XML ดังนี้:
<Button
android:id="@+id/thebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me!"
/>
จากนั้นคุณจะใส่สิ่งนี้ในวิธีการ onCreate () ของคุณ:
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);
ฉันไม่สามารถทดสอบได้ในตอนนี้นี่เป็นรหัสจากหัวของฉัน แต่โดยทั่วไปแล้วแทนที่หรือเพิ่มสีที่คุณต้องการ โดยพื้นฐานในตัวอย่างของฉันคุณจะเริ่มต้นด้วยสีเขียวอ่อนจางเป็นสีขาวเล็กน้อยก่อนที่จะอยู่ตรงกลาง (เพื่อให้จางหายไปมากกว่าการเปลี่ยนแปลงที่รุนแรง) จางจากสีขาวเป็นสีเขียวกลางระหว่าง 45% และ 55% จากนั้น สีเขียวกลางถึงสีเขียวเข้มจาก 55% ถึงจุดสิ้นสุด สิ่งนี้อาจไม่เหมือนรูปร่างของคุณ (ตอนนี้ฉันไม่มีวิธีทดสอบสีเหล่านี้) แต่คุณสามารถแก้ไขเพื่อจำลองแบบของคุณได้
แก้ไข: นอกจากนี้0, 0, 0, theButton.getHeight()
หมายถึงพิกัด x0, y0, x1, y1 ของการไล่ระดับสี โดยพื้นฐานแล้วมันเริ่มต้นที่ x = 0 (ด้านซ้าย), y = 0 (ด้านบน), และทอดยาวไปที่ x = 0 (เราต้องการไล่ระดับแนวตั้งดังนั้นจึงไม่จำเป็นต้องทำมุมซ้าย - ขวา) y = ความสูง ของปุ่ม ดังนั้นการไล่ระดับสีจะทำมุม 90 องศาจากด้านบนของปุ่มไปจนถึงด้านล่างของปุ่ม
แก้ไข: โอเคฉันมีความคิดอีกอย่างที่ใช้ได้ฮ่าฮ่า ตอนนี้มันใช้งานได้ใน XML แต่ควรจะสามารถใช้กับรูปร่างใน Java ได้เช่นกัน มันซับซ้อนและฉันคิดว่ามันมีวิธีทำให้มันง่ายขึ้นในรูปแบบเดียว แต่นี่คือสิ่งที่ฉันได้รับในตอนนี้:
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>
ตกลงดังนั้นโดยทั่วไปฉันได้สร้างการไล่ระดับสีรูปร่างใน XML สำหรับการไล่ระดับสีเขียวแนวนอนตั้งที่มุม 0 องศาจากสีเขียวซ้ายของพื้นที่ด้านบนไปจนถึงสีเขียวที่เหมาะสม ต่อไปฉันทำสี่เหลี่ยมผืนผ้ารูปร่างที่มีสีเทาครึ่งโปร่งใส ฉันค่อนข้างแน่ใจว่าสามารถแทรกลงใน XML ของรายการเลเยอร์โดยตัดไฟล์เพิ่มเติมนี้ออก แต่ฉันไม่แน่ใจ แต่ก็ไม่เป็นไรแล้วส่วนของแฮ็คจะมาอยู่ในไฟล์ layer_list XML ฉันใส่การไล่ระดับสีเขียวเป็นเลเยอร์ด้านล่างจากนั้นวางซ้อนทับครึ่งเป็นเลเยอร์ที่สองชดเชยจากด้านบนลง 50dp เห็นได้ชัดว่าคุณต้องการให้ตัวเลขนี้เป็นครึ่งหนึ่งของขนาดมุมมองของคุณเสมอและไม่ใช่ค่าคงที่ 50dp ฉันไม่คิดว่าคุณสามารถใช้เปอร์เซ็นต์ได้ จากนั้นฉันเพิ่งแทรก TextView ลงในเลย์เอาต์ test.xml ของฉันโดยใช้ไฟล์ layer_list.xml เป็นพื้นหลังของฉัน
Tada!
อีกหนึ่งการแก้ไข : ฉันรู้ว่าคุณสามารถฝังรูปร่างลงในรายการเลเยอร์ที่วาดได้เป็นรายการซึ่งหมายความว่าคุณไม่จำเป็นต้องใช้ไฟล์ XML แยกกันอีก 3 ไฟล์! คุณสามารถได้รับผลลัพธ์เดียวกันโดยรวมสิ่งเหล่านี้:
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>
คุณสามารถเลเยอร์ไอเท็มได้มากเท่าที่คุณต้องการด้วยวิธีนี้! ฉันอาจลองเล่นไปรอบ ๆ และดูว่าฉันจะได้ผลลัพธ์ที่หลากหลายมากขึ้นผ่านทาง Java หรือไม่
ฉันคิดว่านี่เป็นการแก้ไขครั้งสุดท้าย ... : โอเคดังนั้นคุณสามารถกำหนดตำแหน่งผ่าน Java ได้อย่างแน่นอน:
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);
แต่! สิ่งนี้นำไปสู่ปัญหาที่น่ารำคาญอีกประการหนึ่งซึ่งคุณไม่สามารถวัด TextView ได้จนกว่าจะถูกดึงออกมา ฉันยังไม่แน่ใจว่าคุณจะทำสิ่งนี้ให้สำเร็จได้อย่างไร ... แต่การแทรกหมายเลขสำหรับ topInset ด้วยตนเองทำงานได้
ฉันโกหกอีกหนึ่งการแก้ไข
เอาล่ะพบวิธีการปรับปรุง drawable ชั้นนี้เพื่อให้ตรงกับความสูงของภาชนะด้วยตนเอง, รายละเอียดเต็มสามารถพบได้ที่นี่ รหัสนี้ควรเป็นไปตามวิธี 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);
}
});
และฉันทำเสร็จแล้ว! ต๊าย! :)