Các phương pháp hay nhất để sử dụng biểu tượng SVG trên Android là gì?


75

Tôi sắp tạo ứng dụng Android gốc (không dựa trên trình duyệt) đầu tiên của mình và đang tìm kiếm một số phương pháp hay về tạo / cấp phép biểu tượng. Vì nó sẽ hỗ trợ nhiều thiết bị / độ phân giải, tôi nghĩ tốt nhất nên sử dụng SVG để tạo chúng. Có ít nhất lib này: http://code.google.com/p/svg-android/ hứa hẹn cung cấp hỗ trợ cho SVG trên Android.

Cho đến nay, tôi vẫn chưa tìm thấy tài nguyên mô tả việc sử dụng thư viện này hoặc thư viện khác như một phương tiện để hiển thị các Biểu tượng SVG trên thiết bị, vì vậy tôi hơi lưỡng lự trong việc sử dụng nó. Điều tốt nhất mà tôi thấy cho đến nay là sử dụng SVG làm định dạng nguồn để kết xuất trước các biểu tượng dựa trên png ở các độ phân giải khác nhau.

Vì vậy, câu hỏi của tôi là: Các biểu tượng SVG có phải là một lựa chọn tốt để sử dụng trực tiếp trên thiết bị mà không cần đến bước kết xuất trước png (nó có hoạt động không) và nếu, tại sao dường như không ai sử dụng phương pháp này?

Câu trả lời:


30

Đối với Android cũ hơn Lollipop, phương pháp hay nhất cho SVG trên Android là sử dụng một công cụ để chuyển đổi SVG sang PNG ở (các) kích thước mà bạn quan tâm. Hỗ trợ SVG hiện tại cho Android không đầy đủ những gì bạn có khả năng tìm thấy trong tệp SVG, và ngay cả khi có, hỗ trợ không được tích hợp sẵn trong hệ điều hành nên việc sử dụng chúng trực tiếp cho các biểu tượng chắc chắn là không có.

Bắt đầu với Lollipop (API 21) xem Các phương pháp hay nhất để sử dụng biểu tượng SVG trên Android là gì? . Cảm ơn @MarkWhitaker @AustynMahoney đã chỉ ra điều này.


1
Androidify sử dụng thư viện này và nó trông khá toàn diện. Người lib dường như có thể tạo ra Hình ảnh và Vật thể vẽ. Có thể sử dụng điều này để tạo một lớp biểu tượng tùy chỉnh tận dụng điều này không?
user462982 10/03/12

Nếu biểu tượng bạn đang đề cập đến là biểu tượng hiển thị trong trình khởi chạy, thì không. Android không cho phép bạn chỉ định phương pháp để tạo biểu tượng, nó chỉ cho phép bạn xác định biểu tượng bằng tài nguyên của nó.
mah

1
Nếu thư viện bạn đang làm việc có thể xử lý tốt các SVG mà bạn có, bạn có thể làm cho nó hoạt động cho các nút nhưng không thông qua API Android tiêu chuẩn; bạn sẽ cần tạo chế độ xem nút tùy chỉnh. Khoảng 12-18 tháng trước, tôi đã sử dụng thư viện mà bạn đã liên kết và lúc đó nó gặp sự cố với nhiều SVG mà tôi đã tạo trong Inkscape hoặc tải xuống từ nhiều nơi khác nhau. Có lẽ sự hỗ trợ của nó đã được cải thiện kể từ đó, nhưng tôi khuyên bạn nên thử nghiệm nó với SVG chính xác mà bạn định sử dụng trước khi viết nhiều mã tùy chỉnh cho nó.
mah

2
Câu trả lời này chắc chắn không chính xác bây giờ. stackoverflow.com/a/29229005/116938
Austyn Mahoney

1
câu trả lời lạc hậu
bendaf

47

Từ Lollipop (API 21) trở đi, Android định nghĩa lớp VectorDrawable , để xác định các tệp có thể vẽ dựa trên đồ họa vector. Android Studio 1.4 thêm "Vector Asset Studio" để làm việc với chúng dễ dàng hơn, bao gồm tính năng nhập SVG và plugin Gradle mới tạo phiên bản PNG của biểu tượng VectorDrawable tại thời điểm xây dựng cho API 20 trở về trước. Ngoài ra còn có một công cụ của bên thứ ba để chuyển đổi SVG sang VectorDrawables . Hãy nhớ rằng mặc dù các tệp có thể vẽ vectơ có thể được định nghĩa bằng XML, nhưng định dạng tệp không phải là SVG và không phải tất cả các tệp SVG đều có thể được chuyển đổi thành công. Đồ họa đơn giản như biểu tượng sẽ hoạt động tốt.

Nếu bạn vẫn cần tự tạo PNG, bạn sẽ cần tạo các biểu tượng của mình ở nhiều độ phân giải khác nhau . Để dễ dàng tạo các PNG đó, tôi thiết kế các biểu tượng dưới dạng SVG và sau đó xuất sang các kích thước khác nhau bằng Inkscape miễn phí và đa nền tảng. Nó có một số tính năng hay để thiết kế các biểu tượng, bao gồm chế độ xem Biểu tượng xem trước (xem bên dưới) và nó tạo ra các tệp PNG sắc nét đẹp mắt.

nhập mô tả hình ảnh ở đây


2
Thật không may, chức năng Nhập SVG rất rất cơ bản.
Robin

2
Nhóm Android đã phát hành hỗ trợ tương thích ngược cho Vector Assets trong Android Studio 1.4. Tôi đã cập nhật câu trả lời để phản ánh điều này. android-developers.blogspot.com/2015/09/android-studio-14.html
Austyn Mahoney

liên kết hướng dẫn bị thiếu / dẫn đến trang này
V-master

31

Đây là những gì chúng tôi đang sử dụng để chuyển đổi tệp SVG thành nhiều độ phân giải. Ví dụ: để tạo biểu tượng khởi chạy:svg2png -w48 icon.svg

#!/bin/bash -e
# Transforms a SVG into a PNG for each platform
# Sizes extracted from
# http://developer.android.com/design/style/iconography.html

[ -z $2 ] && echo -e "ERROR: filename and one dimension (-w or -h) is required, for example:\nsvg2png -w48 icon.svg\n" && exit 1;
FILENAME=$2
DEST_FILENAME=`echo $2 | sed s/\.svg/\.png/`
FLAG=`echo $1 | cut -c1-2`
ORIGINAL_VALUE=`echo $1 | cut -c3-`

if [ "$FLAG" != "-w" ] && [ "$FLAG" != "-h" ]; then
    echo "Unknown parameter: $FLAG" 
    exit 1
fi

# PARAMETERS: {multiplier} {destination folder}
function export {
  VALUE=$(echo "scale=0; $ORIGINAL_VALUE*$1" | bc -l)
  CMD="inkscape $FLAG$VALUE --export-background-opacity=0 --export-png=src/main/res/$2/$DEST_FILENAME src/main/svg/$FILENAME > /dev/null"
  echo $CMD
  eval $CMD
} 

export 1 drawable-mdpi
export 1.5 drawable-hdpi
export 2 drawable-xhdpi
export 3 drawable-xxhdpi
export 4 drawable-xxxhdpi

Điều tốt để biết, kịch bản hay, rất hữu ích. Tôi có thể tránh nhập SVG vào GIMP hoặc PS. Tôi nghĩ bạn nên thêm một số mẹo về cách sử dụng nó (nó không thành công nếu các thư mục không tồn tại).
jc

16

Tin vui cho mọi người! Kể từ thư viện hỗ trợ Android 23.2, chúng tôi có thể sử dụng svg-s cho đến khi trở lại API cấp 7 !

Nếu bạn chỉ muốn tương thích ngược cho đến khi Lollipop (API 21) kiểm tra câu trả lời của Mark Whitaker , nhưng nếu bạn muốn đi xuống bên dưới, bạn cần thêm những dòng này vào bản build.gradle:

// Gradle Plugin 2.0+ (if you using older version check the library announcement link)
android {  
    defaultConfig {  
        vectorDrawables.useSupportLibrary = true  
    }  
}  

Cũng nên nhớ rằng:

  • thay vì android:srcbạn cần sử dụng app:srcCompatthuộc tính trong ImageViews.
  • bạn không thể sử dụng svg-s trong StateListDrawables hoặc các tệp có thể kéo xml khác, thay vào đó hãy tạo chúng theo chương trình.
  • bạn không thể sử dụng android:backgroundthuộc tính hoặc View.setBackgroundResource()chức năng, hãy sử dụng View.setBackground()thay thế.
  • bạn không thể sử dụng svg-s trong trường hợp Thông báo.

Tôi đã làm điều này, nhưng tôi chỉ thấy svg trên các thiết bị có cấp độ api> 21. có vấn đề gì ở đây?
Morteza Rastgoo

1
Bạn có đang sử dụng thuộc tính màu trong svg của bạn không? bạn có thể tạo một câu hỏi mới và chèn svg và tệp build.gradle của bạn vào đó không?
bendaf,

1
@Morteza kiểm tra câu trả lời này cũng có, nếu nó vẫn không làm việc tại bạn: stackoverflow.com/a/36661438/3162918
bendaf

8

Vì câu trả lời của nacho-coloma đã giúp tôi, tôi đã lấy kịch bản xuất sắc của anh ấy và làm cho nó dễ dàng hơn một chút để sử dụng hàng ngày.

Đầu tiên:

  1. Tạo thư mục drawable-svgbên cạnh thư mục của bạn res.
  2. Đặt các tệp svg của bạn và tập lệnh này vào drawable-svg.
  3. Làm cho tập lệnh có thể thực thi được.
  4. Chạy nó. Trong Ubuntu, bạn chỉ cần nhấp đúp vào nó trong Nautilus và làm cho nó chạy trong một thiết bị đầu cuối.

Và sau này khi bạn nhận được các tệp svg mới:

  1. Đặt các tệp svg mới vào drawable-svgvà chạy lại tập lệnh.

Theo mặc định, nó sẽ làm những gì bạn muốn: Chia tỷ lệ mọi tệp svg thành tệp png và đưa chúng vào ../res/drawable-mdpi, ../res/drawable-hdpiv.v.

Tập lệnh có hai tham số:

  1. Mẫu tệp svg để chia tỷ lệ, mặc định: *.svg
  2. Thư mục cơ sở cho put, default ../res/(tức là resthư mục của bạn với thiết lập được đề cập ở trên).

Bạn có thể thử nghiệm bằng cách chia tỷ lệ một svg thành pngs trong thư mục hiện tại như sau:

$ ./svg2png test.svg .

Hoặc chỉ cần xử lý tất cả các hình ảnh:

$ ./svg2png

Tôi đoán bạn có thể đặt drawable-svgbên trong thư mục res, nhưng tôi chưa xem xét những gì được bao bọc trong APK cuối cùng. Ngoài ra, các tệp svg của tôi có -tên của chúng, điều mà Android không thích và tập lệnh của tôi sẽ chăm sóc đổi tên các tệp png thành một thứ hợp lệ trên Android.

Tôi đang sử dụng ImageMagick cho việc chuyển đổi hơi tiêu chuẩn hơn Inkscape (mặc dù tôi thích cách tiếp cận). Cả hai phương pháp đều có trong script để tham khảo.

Đây là kịch bản:

#!/bin/bash

scalesvg ()
{
    svgfile="$1"
    pngdir="$2"
    pngscale="$3"
    qualifier="$4"

    svgwidthxheight=$(identify "$svgfile" | cut -d ' ' -f 3)
    svgwidth=${svgwidthxheight%x*}
    svgheight=${svgwidthxheight#*x}

    pngfile="$(basename $svgfile)" # Strip path.
    pngfile="${pngfile/.svg/.png}" # Replace extension.
    pngfile="${pngfile/[^A-Za-z0-9._]/_}" # Replace invalid characters.
    pngfile="$pngdir/$qualifier/$pngfile" # Prepend output path.

    if [ ! -d $(dirname "$pngfile") ]; then
        echo "WARNING: Output directory does not exist: $(dirname "$pngfile")"
        #echo "Exiting"
        #exit 1
        echo "Outputting here instead: $pngfile"
        pngfile="$qualifier-${svgfile/.svg/.png}"
    fi

    pngwidth=$(echo "scale=0; $svgwidth*$pngscale" | bc -l)
    pngheight=$(echo "scale=0; $svgheight*$pngscale" | bc -l)
    pngdensity=$(echo "scale=0; 72*$pngscale" | bc -l) # 72 is default, 

    echo "$svgfile ${svgwidth}×${svgheight}px -> $pngfile ${pngwidth}×${pngheight}px @ $pngdensity dpi"

    convert -background transparent -density $pngdensity "$svgfile" "$pngfile"
    #inkscape -w${pngwidth} --export-background-opacity=0 --export-png="$pngfile" "$svgfile" > /dev/null
    #convert "$svgfile" -background transparent -scale ${pngwidth}x${pngheight} "$pngfile"
}



svgfiles="$1"
svgfiles="${svgfiles:=*.svg}" # Default to input all *.svg in current dir.

pngdir="$2"
pngdir="${pngdir:=../res}" # Default to place output pngs to ../res, ie. ../res/drawable-hdpi etc.

for svgfile in $svgfiles; do
    echo "Scaling $svgfile ..."
    scalesvg "$svgfile" "$pngdir" 0.75 drawable-ldpi
    scalesvg "$svgfile" "$pngdir" 1    drawable-mdpi
    scalesvg "$svgfile" "$pngdir" 1.5  drawable-hdpi
    scalesvg "$svgfile" "$pngdir" 2    drawable-xhdpi
    scalesvg "$svgfile" "$pngdir" 3    drawable-xxhdpi
    scalesvg "$svgfile" "$pngdir" 4    drawable-xxxhdpi
done

echo -n "Done."
read # I've made it wait for Enter -- convenient when run from Nautilus.


5

Thư viện hỗ trợ Android 23.2 Hỗ trợ Bản vẽ vector và Bản vẽ vector hoạt hình

  1. thêm vectorDrawables.useSupportLibrary = truevào tệp build.gradle của bạn.
  2. Sử dụng app:srcCompat="@drawable/ic_add"thay cho android:src="..."hoặc setImageResource()cho ImageView của bạn

http://android-developers.blogspot.sk/2016/02/android-support-library-232.html


Tôi đã làm điều này, nhưng tôi chỉ thấy svg trên các thiết bị có cấp độ api> 21. có vấn đề gì ở đây?
Morteza Rastgoo

@MortezaRastgoo Bạn có thể vui lòng hiển thị mã của bạn ở đâu đó không? Tôi không thể đoán nếu không có nó. Nó hoạt động tốt cho tôi.
Lordmegamax

3

Các biểu tượng SVG không phải là một lựa chọn tốt để sử dụng trực tiếp trên thiết bị nếu chúng cần được chia tỷ lệ thành nhiều kích thước khác nhau, đó thường là lý do tại sao bạn muốn sử dụng định dạng vectơ ngay từ đầu. Một biểu tượng lớn sẽ không bao giờ giảm tỷ lệ một cách duyên dáng bởi vì, tốt, màn hình máy tính được tạo ra từ pixel. Vì vậy, các dòng của hình ảnh vectơ có thể được căn chỉnh "ở giữa các pixel", tạo ra một đường viền mờ. Hơn nữa, các biểu tượng lớn cần nhiều chi tiết hơn các biểu tượng nhỏ, cần rất ít chi tiết. Một biểu tượng chi tiết trông không đẹp ở kích thước rất nhỏ và một biểu tượng đơn giản trông không đẹp khi được thu nhỏ thành kích thước rất lớn. Gần đây tôi đã đọc một bài báo xuất sắc về điều này của một nhà thiết kế giao diện người dùng chuyên nghiệp: Về các biểu tượng vector đó .


Bạn có thể kiểm soát những điều đó ở một mức độ nhất định với shape-rendering. Tuy nhiên, sự hỗ trợ rất thưa thớt.
Joey

Cảm ơn @Joey, thật tốt khi biết. Tuy nhiên, ngay cả điều đó cũng không cho phép bạn chỉ định rằng một phần tử sẽ bị loại bỏ hoàn toàn nếu hình ảnh được hiển thị đủ nhỏ.
ZeroOne

4
Điều ngẫu nhiên mà tôi vừa nghĩ ra: Các kích thước biểu tượng khác nhau trong các ứng dụng thường là do mật độ pixel khác nhau của thiết bị mục tiêu - do đó tất cả chúng đều xuất hiện ở cùng một kích thước hình ảnh . Vì vậy, chúng thực sự không cần nhiều hơn hoặc ít chi tiết hơn tùy thuộc vào kích thước. Ít nhất là không phải trong bối cảnh này. Tôi hiện đang sử dụng SVG làm định dạng nguồn cho các biểu tượng trong hai ứng dụng Android tại nơi làm việc và điều duy nhất bạn có thể cần chú ý là căn chỉnh các cạnh theo ranh giới pixel cho kích thước đường cơ sở (mdpi). Android cũng gợi ý rằng các biểu tượng sử dụng ít nhất hai pixel cho các đường ở kích thước đường cơ sở.
Joey

1
Tôi đang sử dụng Inkscape để hiển thị chúng ở các độ phân giải cần thiết; vì dù sao thì nghệ sĩ của chúng tôi cũng vẽ các biểu tượng vector đó là cách tiếp cận dễ dàng nhất. Nó cũng cho phép tạo màu sắc của các biến thể độ mờ một cách nhanh chóng (ví dụ: các cặp biểu tượng được bật / tắt), đây là một lợi ích rất lớn của SVG. Sự khác biệt khi giảm tỷ lệ PNG lớn nhất là nhỏ, nhưng có thể nhìn thấy một cách tinh tế (các cạnh không hoàn toàn sắc nét vì bạn cũng đang giảm tỷ lệ răng cưa).
Joey

1
Bạn sẽ chỉ cần một phiên bản cho độ phân giải cực thấp và một phiên bản cho tất cả các phiên bản khác. so với những gì, 5-6 bitmap khác nhau mà bạn phải cung cấp cho Android ngay bây giờ? Bên cạnh đó, tại sao lại giới hạn định dạng hình ảnh được hỗ trợ: hãy để người dùng quyết định định dạng họ thích.
velis


2

Tôi vừa mới bắt đầu sử dụng Victor , một thư viện mã nguồn mở của Trello, để chuyển đổi tệp SVG sang tệp PNG có độ phân giải yêu cầu khác nhau trong thời gian xây dựng.

PROS

  • Bạn sẽ không phải chạy tập lệnh hoặc công cụ để tạo các tệp PNG khác nhau mỗi khi bạn thay đổi hoặc thêm biểu tượng. (Bạn cần nhấn vào Xây dựng lại trong Android Studio khi bạn đã thêm tệp svg mới hoặc đổi tên tệp hiện có)
  • Không có PNG trong nguồn của bạn, vì vậy sẽ ít lộn xộn hơn.

CONS

  • Nhược điểm duy nhất mà tôi thấy cho đến nay là Android Studio chưa nhận ra các tài nguyên được tạo trong XML, vì vậy bạn sẽ nhận được một số cảnh báo màu đỏ trong các tệp XML của mình và bạn không có tính năng tự động hoàn thành cho các tệp có thể kéo dựa trên SVG của mình. Tuy nhiên, nó xây dựng tốt và vấn đề này sẽ được khắc phục trong phiên bản Android Studio trong tương lai.

Nếu bạn sử dụng SVG được tạo bởi http://materialdesignicons.com/, hãy đảm bảo tải xuống toàn bộ tệp hoặc sao chép từ tab 'Tệp SVG' khi chọn 'Xem SVG'


1

svg thật tuyệt vời. ai muốn sử dụng svg:

nhấp chuột phải vào "new / Vector Asset" có thể vẽ được, chọn "material icon" cho các biểu tượng mặc định và "locale SVG file" cho tệp của bạn trong ổ cứng máy tính của bạn và trong tên loại "resource name" cho tệp svg rồi nhấp vào nút "next" và hoàn thành"

và bạn có thể sử dụng nó trong drawable. màu tô phải là mã cứng.

ví dụ đơn giản

navigation_toggle.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFFFFF"
        android:pathData="M3,18h18v-2H3v2zm0,-5h18v-2H3v2zm0,-7v2h18V6H3z"/>
</vector>

0

Tôi chưa bao giờ gặp nhiều may mắn khi chạy các tập lệnh shell Linux trong Cygwin trên Windows. Vì vậy, đây là một tệp lô thực hiện những gì tập lệnh bash của Nacho Coloma thực hiện. Một điểm khác biệt nhỏ là tệp hàng loạt này yêu cầu cả đầu vào và tên tệp đầu ra, như trong "svg2png -w24 input.svg output.png".

Thiết lập một thư mục "svg" trong thư mục src / chính của dự án của bạn và sao chép các tệp SVG của bạn và tệp hàng loạt này vào thư mục đó, theo hướng dẫn của Stephan. Chạy tệp loạt từ thư mục svg. Nếu bạn đang sử dụng Windows 32-bit, thì bạn có thể sẽ cần phải thay đổi đường dẫn đến Inkscape để sử dụng "Program Files (x86)".

@echo off
echo Convert an SVG file to a PNG resource file with multiple resolutions.

rem Check the arguments
set temp=%1
set switch=%temp:~0,2%
set pixels=%temp:~2%
if not "%switch%"=="-w" (
if not "%switch%"=="-h" (
echo Error:  Invalid image width or height switch.  Use -w or -h, with target image size in dp appended.
goto :error
))
echo %pixels%| findstr /r /c:"^[1-9][0-9]*$" >nul
if errorlevel 1 (
echo Error:  Invalid numeric image size.  Image size must be a positive integer.
goto :error
)
if "%3"=="" (
echo Error:  Not enough arguments.
goto :error
)
if not "%4"=="" (
echo Error:  Too many arguments.
goto :error
)

call :export %1 %2 %3 mdpi
call :export %1 %2 %3 hdpi
call :export %1 %2 %3 xhdpi
call :export %1 %2 %3 xxhdpi
call :export %1 %2 %3 xxxhdpi
exit /b

:export
rem parameters: <width/height> <input-file> <output-file> <density>

set temp=%1
set switch=%temp:~0,2%
set pixels=%temp:~2%

if %4==mdpi set /a size=%pixels%
if %4==hdpi set /a size=%pixels%*3/2
if %4==xhdpi set /a size=%pixels%*2
if %4==xxhdpi set /a size=%pixels%*3
if %4==xxxhdpi set /a size=%pixels%*4

echo %size% pixels ../res/drawable-%4/%3
"C:\Program Files\Inkscape\inkscape.exe" %switch%%size% --export-background-opacity=0 --export-png=../res/drawable-%4/%3 %2
exit /b

:error
echo Synopsis: svg2png -w^<width-pixels^>^|-h^<height-pixels^> ^<input-file^> ^<output-file^>
echo Example:  svg2png -w24 "wifi white.svg" wifi_connect_24dp.png
exit /b
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.