Cách căn giữa vectơ có thể vẽ được trong danh sách lớp mà không cần chia tỷ lệ


102

Tôi đang cố gắng sử dụng a VectorDrawabletrong a LayerListmà không chia tỷ lệ vector. Ví dụ:

<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_48dpId có thể vẽ được định nghĩa là:

<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>

Hiệu ứng mong muốn là để biểu tượng dấu kiểm được căn giữa trong lớp có thể vẽ được mà không cần chia tỷ lệ. Vấn đề là, danh sách lớp ở trên khiến biểu tượng dấu kiểm được thu nhỏ để phù hợp với kích thước lớp.

Tôi có thể tạo ra hiệu ứng mong muốn nếu tôi thay thế vectơ có thể vẽ bằng PNG cho mỗi mật độ và sửa đổi danh sách lớp như vậy:

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

Có cách nào tôi có thể làm điều này bằng cách sử dụng một VectorDrawable?


11
Có vẻ như đây có thể chỉ là một lỗi trong API 21/22. Tôi vừa thử nghiệm trên thiết bị API 23 và vector có thể vẽ được căn giữa chính xác.
ashughes

1
Bạn nên trả lời câu hỏi của riêng bạn và chấp nhận nó. Bằng cách đó, nó hiển thị nhiều hơn và câu hỏi không hiển thị là chưa được trả lời.
Marcin Koziński

1
Tôi chưa trả lời câu hỏi của mình vì tôi chưa có câu trả lời cho những việc cần làm trên API 21/22. Giải pháp tạm thời của tôi là sử dụng PNG thay vì vectơ. Tuy nhiên, hy vọng vẫn tìm ra cách làm cho các vectơ hoạt động.
ashughes

1
Tôi đã gặp sự cố ở đây: code.google.com/p/android/issues/detail?id=219600
toobsco42

Điều này đã được sửa trong API 23, vì vậy tôi đoán báo cáo lỗi của bạn sẽ được đánh dấu là đã sửa.
ashughes

Câu trả lời:


29

Tôi đã gặp phải vấn đề tương tự khi cố gắng căn giữa các vectơ có thể vẽ trên một danh sách nhiều lớp.

Tôi có một cách giải quyết khác, nó không hoàn toàn giống nhau nhưng nó hoạt động, bạn cần đặt kích thước cho toàn bộ tệp có thể vẽ và thêm phần đệm vào mục vectơ:

<?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>

Kích thước của hình dạng ở trên đặt kích thước của toàn bộ hình có thể vẽ, trong ví dụ này là 120dp, phần đệm trên mục thứ hai, 24dp trong ví dụ này, căn giữa hình ảnh vectơ.

Nó không giống với cách sử dụng gravity="center"nhưng cách làm việc của nó là sử dụng vectơ trong API 21 và 22.


2
Điều này có vẻ như nó sẽ yêu cầu bạn biết kích thước chính xác của có thể vẽ (để đặt kích thước hình dạng), thay vì để nó lấp đầy toàn bộ không gian mà nó được đặt với séc có thể vẽ được đặt ở giữa.
ashughes

1
Có thể không biết kích thước nhưng bạn không thể thay đổi phần đệm bằng phương pháp này, bạn có thể xếp các phần có thể kéo lên trên nhau trong các lần xem hình ảnh. Như tôi đã nói ở trên không có giải pháp hoàn hảo cho một gravity="center"trong API 21 và 22.
Nicolas Tyler

Nó không hoạt động khi sử dụng với windowBackground. Kích thước rõ ràng không làm gì trong trường hợp này. Và nó cũng không hoạt động nếu tôi đặt danh sách lớp bên trong danh sách lớp khác.
Vsevolod Ganin

19

Đang đấu tranh với cùng một vấn đề. Cách duy nhất tôi tìm thấy để khắc phục điều này và tránh việc có thể kéo được mở rộng quy mô là đặt kích thước có thể vẽ và sử dụng trọng lực để căn chỉnh nó:

<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>

Hy vọng nó giúp!


34
Điều này không hữu ích trên API 21-22, vì widththuộc tính không có sẵn trên các cấp API đó. Trên API 23, những thứ này không cần thiết, vì lỗi đã được sửa và có thể kéo không bị kéo dài nữa.
WonderCsabo

3
Điều này không làm việc một cách chính xác cho API 27, hình ảnh được kéo dài đến độ toàn màn hình
Konstantin Konopko

8

Giải pháp đã chỉnh sửa sẽ làm cho SplashScreen của bạn trông tuyệt vời trên tất cả các API bao gồm API21 đến API23

Trước hết đọc này bài viết và làm theo cách tốt để thực hiện một màn hình giật gân.

Nếu biểu trưng của bạn bị méo hoặc không vừa và bạn chỉ nhắm mục tiêu APIs24 +, bạn có thể chỉ cần thu nhỏ véc tơ có thể vẽ trực tiếp trong tệp xml của nó như sau:

<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>

trong đoạn mã trên, tôi đang thay đổi tỷ lệ có thể vẽ mà tôi đã vẽ trên canvas 640x640 thành 240x240. sau đó tôi chỉ cần đặt nó vào màn hình giật gân của tôi có thể vẽ như vậy và nó hoạt động tuyệt vời:

<?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>

mã của tôi thực sự chỉ vẽ hình tam giác trong hình ở dưới cùng nhưng ở đây bạn thấy những gì bạn có thể đạt được với điều này. Độ phân giải cuối cùng cũng tuyệt vời trái ngược với các cạnh pixel mà tôi nhận được khi sử dụng bitmap. vì vậy hãy sử dụng vector có thể vẽ được bằng mọi cách (có một trang web tên là vectr mà tôi đã sử dụng để tạo của tôi mà không cần phải tải xuống phần mềm chuyên dụng).

CHỈNH SỬA để làm cho nó hoạt động cũng trên API21-22-23

Mặc dù giải pháp trên hoạt động cho các thiết bị chạy API24 +, tôi thực sự thất vọng sau khi cài đặt ứng dụng của mình một thiết bị chạy API22. Tôi nhận thấy rằng màn hình giật gân lại đang cố lấp đầy toàn bộ khung cảnh và trông giống như đồ dở hơi. Sau khi xé đôi lông mày của mình trong nửa ngày, cuối cùng tôi đã buộc phải có một giải pháp bằng sức mạnh ý chí tuyệt đối.

bạn cần tạo một tệp thứ hai có tên giống hệt như splashscreen xml (giả sử như splash_screen.xml) và đặt nó vào 2 thư mục có tên là drawable-v22 và drawable-v21 mà bạn sẽ tạo trong thư mục res / (để xem chúng bạn nhé. phải thay đổi chế độ xem dự án của bạn từ Android sang Dự án). Điều này phục vụ cho việc yêu cầu điện thoại của bạn chuyển hướng đến các tệp được đặt trong các thư mục đó bất cứ khi nào thiết bị liên quan chạy API tương ứng với hậu tố -vXX trong thư mục có thể kéo, hãy xem liên kết này . đặt mã sau vào danh sách Lớp của tệp splash_screen.xml mà bạn tạo trong các thư mục này:

<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>

đây là cách các thư mục trông

Vì một số lý do cho các API này, bạn phải bọc tệp có thể vẽ của mình trong một bitmap để làm cho nó hoạt động và cho kết quả cuối cùng trông giống nhau. Vấn đề là bạn phải sử dụng aproach với các thư mục có thể vẽ bổ sung vì phiên bản thứ hai của tệp splash_screen.xml sẽ dẫn đến màn hình giật gân của bạn hoàn toàn không được hiển thị trên các thiết bị chạy API cao hơn 23. Bạn cũng có thể phải đặt phiên bản đầu tiên của splash_screen.xml thành drawable-v24 khi android đặt mặc định vào thư mục drawable-vXX gần nhất mà nó có thể tìm thấy cho các tài nguyên.

màn hình giật gân của tôi


4

Tôi hiện đang làm việc trên một màn hình giật gân với một vector có thể vẽ được căn giữa theo cả chiều ngang và chiều dọc. Đây là những gì tôi nhận được trên API cấp 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>

Nếu bạn muốn điều chỉnh kích thước của vector có thể vẽ, hãy sửa đổi android:widthandroid:heightcác thuộc tính ở trên, không nhất thiết phải sửa đổi kích thước có thể vẽ ban đầu.

Ngoài ra, kinh nghiệm của tôi là KHÔNG đặt vector có thể vẽ vào thẻ bitmap, điều này không bao giờ hiệu quả với tôi. Bitmap dành cho tệp định dạng .png, .jpg và .gif, không dành cho vector có thể vẽ được.

Tài liệu tham khảo

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

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


1
Thông tin hữu ích về các tệp có thể vẽ vectơ cần phải nằm trong thẻ <item> thay vì thẻ <bitmap>.
FrostRocket
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.