วิธีจัดกึ่งกลางเวกเตอร์ที่วาดได้ในรายการเลเยอร์โดยไม่ต้องปรับขนาด


105

ฉันกำลังพยายามใช้VectorDrawablea LayerListโดยไม่ปรับขนาดเวกเตอร์ ตัวอย่างเช่น:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
    <item android:gravity="center" android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

ic_check_white_48dpรหัสที่ดึงได้กำหนดเป็น:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="48dp"
        android:height="48dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

เอฟเฟกต์ที่ต้องการคือให้ไอคอนตรวจสอบอยู่กึ่งกลางในเลเยอร์ที่วาดได้โดยไม่ต้องปรับขนาด ปัญหาคือรายการเลเยอร์ด้านบนทำให้ไอคอนกาเครื่องหมายถูกปรับขนาดให้พอดีกับขนาดเลเยอร์

ฉันสามารถสร้างเอฟเฟกต์ที่ต้องการได้หากฉันแทนที่เวกเตอร์ที่วาดได้ด้วย PNG สำหรับแต่ละความหนาแน่นและแก้ไขรายการเลเยอร์ดังนี้:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
    <item>
        <bitmap android:gravity="center" android:src="@drawable/ic_check_white_48dp"/>
    </item>
</layer-list>

มีวิธีใดบ้างที่ฉันสามารถทำได้โดยใช้ a VectorDrawable?


11
ดูเหมือนว่านี่อาจเป็นข้อบกพร่องใน API 21/22 ฉันเพิ่งทดสอบบนอุปกรณ์ API 23 และเวกเตอร์ที่วาดได้อยู่กึ่งกลางอย่างถูกต้อง
ashughes

1
คุณควรตอบคำถามของคุณเองและยอมรับมัน ด้วยวิธีนี้จะเห็นได้ชัดเจนมากขึ้นและคำถามจะไม่แสดงว่ายังไม่มีคำตอบ
Marcin Koziński

1
ฉันยังไม่ได้ตอบคำถามของฉันเพราะฉันยังไม่มีคำตอบว่าจะทำอย่างไรกับ API 21/22 วิธีแก้ปัญหาชั่วคราวของฉันคือใช้ PNG แทนเวกเตอร์ หวังว่าจะยังคงหาวิธีทำให้เวกเตอร์ทำงานได้
ashughes

1
ฉันเปิดปัญหาที่นี่: code.google.com/p/android/issues/detail?id=219600
toobsco42

สิ่งนี้ได้รับการแก้ไขแล้วใน API 23 ดังนั้นฉันเดาว่ารายงานข้อบกพร่องของคุณจะถูกทำเครื่องหมายว่าแก้ไขแล้ว
ashughes

คำตอบ:


30

ฉันพบปัญหาเดียวกันกับการพยายามจัดศูนย์เวกเตอร์ที่วาดได้ในรายการแบบเลเยอร์

ฉันมีวิธีแก้ปัญหาไม่เหมือนกันทุกประการ แต่ใช้งานได้คุณต้องกำหนดขนาดสำหรับสิ่งที่วาดได้ทั้งหมดและเพิ่มช่องว่างในรายการเวกเตอร์:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <size android:height="120dp" android:width="120dp"/>
            <solid android:color="@color/grid_item_activated"/>
        </shape>
    </item>
    <item android:top="24dp"
          android:bottom="24dp"
          android:left="24dp"
          android:right="24dp"
          android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

ขนาดของรูปร่างด้านบนกำหนดขนาดของสิ่งที่วาดได้ทั้งหมด 120dp ในตัวอย่างนี้ช่องว่างในรายการที่สอง 24dp ในตัวอย่างนี้จะจัดกึ่งกลางภาพเวกเตอร์

มันไม่เหมือนกับการใช้gravity="center"แต่วิธีการทำงานของการใช้เวกเตอร์ใน API 21 และ 22


3
ดูเหมือนว่าคุณจะต้องรู้ขนาดที่แน่นอนของสิ่งที่ดึงได้ (เพื่อกำหนดขนาดรูปร่าง) แทนที่จะปล่อยให้มันเต็มพื้นที่ทั้งหมดที่ตั้งค่าไว้โดยให้เช็คที่ดึงได้อยู่ตรงกลาง
ashughes

1
เป็นไปได้ที่จะไม่ทราบขนาด แต่คุณไม่สามารถเปลี่ยนช่องว่างภายในได้ด้วยวิธีนี้คุณสามารถวางเลเยอร์ drawables ไว้ด้านบนของกันและกันในมุมมองภาพ ตามที่ฉันระบุไว้ข้างต้นไม่มีโซลูชันที่สมบูรณ์แบบสำหรับgravity="center"API 21 และ 22
Nicolas Tyler

ไม่ทำงานเมื่อใช้กับwindowBackground. ขนาดที่ชัดเจนจะไม่ทำอะไรในกรณีนี้ และมันก็ไม่ได้ผลเช่นกันถ้าฉันใส่รายการเลเยอร์ไว้ในรายการเลเยอร์อื่น
Vsevolod Ganin

20

กำลังต่อสู้กับปัญหาเดิม ๆ วิธีเดียวที่ฉันพบในการแก้ไขปัญหานี้และหลีกเลี่ยงสิ่งที่วาดได้เพื่อปรับขนาดคือกำหนดขนาดที่ดึงได้และใช้แรงโน้มถ่วงเพื่อจัดแนว:

<layer-list>
    <item android:drawable="@color/grid_item_activated"/>
     <item
        android:gravity="center"
        android:width="48dp"
        android:height="48dp"
        android:drawable="@drawable/ic_check_white_48dp"/>
</layer-list>

หวังว่าจะช่วยได้!


35
สิ่งนี้ไม่ช่วยใน API 21-22 เนื่องจากwidthแอตทริบิวต์ไม่พร้อมใช้งานในระดับ API เหล่านั้น ใน API 23 ไม่จำเป็นต้องใช้สิ่งเหล่านี้เนื่องจากข้อบกพร่องได้รับการแก้ไขและไม่ยืดออกอีกต่อไป
WonderCsabo

3
สิ่งนี้ทำงานไม่ถูกต้องสำหรับ API 27 ภาพถูกขยายเป็นแบบเต็มหน้าจอ
Konstantin Konopko

8

แก้ไขโซลูชันที่จะทำให้ SplashScreen ของคุณดูดีในทุก API รวมถึง API21 ถึง API23

ก่อนอื่นอ่านสิ่งนี้บทความและปฏิบัติตามวิธีที่ดีในการทำหน้าจอสาด

หากโลโก้ของคุณบิดเบี้ยวหรือไม่พอดีและคุณกำหนดเป้าหมายเฉพาะ APIs24 + คุณสามารถย่อขนาดเวกเตอร์ที่วาดได้โดยตรงในไฟล์ xml ดังนี้:

<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="640"
android:viewportHeight="640"
android:width="240dp"
android:height="240dp">
<path
    android:pathData="M320.96 55.9L477.14 345L161.67 345L320.96 55.9Z"
    android:strokeColor="#292929"
    android:strokeWidth="24" />
</vector>

ในโค้ดด้านบนฉันกำลังปรับขนาดของ drawable ที่ฉันวาดบนผืนผ้าใบขนาด 640x640 เป็น 240x240 จากนั้นฉันก็วางไว้ในหน้าจอสแปลชของฉันที่วาดได้แบบนั้นและมันก็ใช้งานได้ดี:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque"
android:paddingBottom="20dp" android:paddingRight="20dp" android:paddingLeft="20dp" android:paddingTop="20dp">

<!-- The background color, preferably the same as your normal theme -->
<item>
    <shape>
        <size android:height="120dp" android:width="120dp"/>
        <solid android:color="@android:color/white"/>
    </shape>
</item>

<!-- Your product logo - 144dp color version of your app icon -->
<item
    android:drawable="@drawable/logo_vect"
    android:gravity="center">

</item>
</layer-list>

รหัสของฉันเป็นเพียงการวาดสามเหลี่ยมในภาพด้านล่าง แต่คุณจะเห็นสิ่งที่คุณสามารถทำได้จากสิ่งนี้ ในที่สุดความละเอียดก็ยอดเยี่ยมเมื่อเทียบกับขอบพิกเซลที่ฉันได้รับเมื่อใช้บิตแมป ดังนั้นใช้เวกเตอร์ที่วาดได้ทุกวิถีทาง (มีไซต์ชื่อ vectr ที่ฉันใช้สร้างของฉันโดยไม่ต้องดาวน์โหลดซอฟต์แวร์พิเศษ)

แก้ไขเพื่อให้ใช้งานได้บน API21-22-23

ในขณะที่โซลูชันข้างต้นใช้ได้กับอุปกรณ์ที่ใช้ API24 + ฉันรู้สึกผิดหวังมากหลังจากติดตั้งแอปของฉันอุปกรณ์ที่ใช้ API22 ฉันสังเกตเห็นว่าหน้าจอสแปลชกำลังพยายามเติมเต็มมุมมองทั้งหมดอีกครั้งและดูเหมือนอึ หลังจากฉีกคิ้วของฉันออกมาครึ่งวันในที่สุดฉันก็บังคับวิธีแก้ปัญหาด้วยจิตตานุภาพที่แท้จริง

คุณต้องสร้างไฟล์ที่สองที่มีชื่อเหมือนกับ xml ของ splashscreen (สมมติว่า splash_screen.xml) และวางลงใน 2 โฟลเดอร์ที่เรียกว่า drawable-v22 และ drawable-v21 ที่คุณจะสร้างใน res / โฟลเดอร์ (เพื่อให้คุณเห็น ต้องเปลี่ยนมุมมองโครงการของคุณจาก Android เป็นโครงการ) สิ่งนี้ทำหน้าที่บอกให้โทรศัพท์ของคุณเปลี่ยนเส้นทางไปยังไฟล์ที่อยู่ในโฟลเดอร์เหล่านั้นเมื่อใดก็ตามที่อุปกรณ์ที่เกี่ยวข้องเรียกใช้ API ที่สอดคล้องกับคำต่อท้าย -vXX ในโฟลเดอร์ที่วาดได้โปรดดูลิงก์นี้ วางโค้ดต่อไปนี้ในรายการ Layer ของไฟล์ splash_screen.xml ที่คุณสร้างในโฟลเดอร์เหล่านี้:

<item>
<shape>
    <size android:height="120dp" android:width="120dp"/>
    <solid android:color="@android:color/white"/>
</shape>
</item>

<!-- Your product logo - 144dp color version of your app icon -->
<item android:gravity="center">
    <bitmap android:gravity="center"
        android:src="logo_vect"/>

</item>

นี่คือลักษณะของโฟลเดอร์

ด้วยเหตุผลบางประการสำหรับ API เหล่านี้คุณต้องรวมไฟล์ที่วาดได้ของคุณไว้ในบิตแมปเพื่อให้มันใช้งานได้และทำให้ผลลัพธ์สุดท้ายดูเหมือนกัน ปัญหาคือคุณต้องใช้ aproach กับโฟลเดอร์ aditional drawable เนื่องจากไฟล์ splash_screen.xml เวอร์ชันที่สองจะทำให้หน้าจอเริ่มต้นของคุณไม่แสดงเลยบนอุปกรณ์ที่ใช้ API ที่สูงกว่า 23 นอกจากนี้คุณอาจต้องวาง splash_screen.xml เวอร์ชันแรกลงใน drawable-v24 เป็นค่าเริ่มต้นของ Android เป็นโฟลเดอร์ drawable-vXX ที่ใกล้เคียงที่สุดที่สามารถค้นหาทรัพยากรได้

หน้าจอของฉัน


4

ตอนนี้ฉันกำลังทำงานบนหน้าจอสแปลชที่มีเวกเตอร์ที่วาดได้ตรงกลางทั้งแนวนอนและแนวตั้ง นี่คือสิ่งที่ฉันได้รับจาก API ระดับ 25:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">

<!-- background color, same as theme -->
<item android:drawable="@android:color/white"/>

<!-- app logo -->

<item
    android:drawable="@drawable/my_app_logo"
    android:gravity="center_horizontal|center_vertical"
    android:width="200dp"
    android:height="200dp"
    />
</layer-list>

หากคุณต้องการปรับขนาดของเวกเตอร์ที่วาดได้ให้แก้ไขandroid:widthและandroid:heightแอตทริบิวต์ด้านบนไม่จำเป็นต้องแก้ไขต้นฉบับที่วาดได้

นอกจากนี้ประสบการณ์ของฉันคืออย่าใส่เวกเตอร์ที่วาดได้ในแท็กบิตแมปซึ่งไม่เหมาะกับฉัน บิตแมปใช้สำหรับไฟล์รูปแบบ. png, .jpg และ. gif ไม่ใช่สำหรับเวกเตอร์ที่วาดได้

ข้อมูลอ้างอิง

https://developer.android.com/guide/topics/resources/drawable-resource#LayerList

https://developer.android.com/guide/topics/resources/more-resources.html#Dimension


1
สิ่งที่ดีเกี่ยวกับสิ่งที่วาดได้เวกเตอร์จำเป็นต้องอยู่ภายในแท็ก <item> แทนที่จะเป็นแท็ก <bitmap>
FrostRocket
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.