+4

Android Làm Việc Với SVG / vector drawables

Trong khi phát triển các ứng dụng android, việc hỗ trợ nhiều thiết bị với những độ phân giải khác nhau đôi khi trở thành cơn ác mộng đối với những nhà phát triển ứng dụng. Việc bao gồm nhiều image cho những độ phân giải khác nhau sẽ làm tăng kích thước của project. Giải pháp ở đây là sử dụng đồ hoạ véc to (Vector Graphics ) chẳng hạn như SVG images. Trong khi android vẫn chưa hỗ trợ SVGs (Scalable Vector Graphics) trực tiếp với sự ra mắt của Lollipop một class mới đã được giới thiệu gọi là VectorDrawable cái này cho phép những nhà thiết kế, những nhà phát triên vẽ những image giống nhau chỉ sử dụng duy nhất code. Giải thích đơn giản một chú Đồ hoạ vector là cách miêu tả những thành phần đồ hoạ bằng cách sử dụng các hình dạng hình học .

VectorDrawable là gì ?

Cái tên nói lên tất cả, vector drawables là dưạ trên đồ hoạ vector, đồ hoạ véctor là một cách mô tả các thành phần đồ hoạ sử dụng cách hình dạng hình học. Nó tương tự như một file SVG. Trong android VectorDrawable được tạo ra như là một file XML. Bây giờ không cần tạo ra những image với các size khác nhau cho mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi ... Chúng tôi cần duy nhất một file vector cho tất cả các divice với những độ phân giải khác nhau. Ngoài ra cho các version android cũ hơn không hỗ trợ vector drawables, Vector Asset Studio có thể biến các vector drawables của bạn vào các kích thước bitmap khác nhau cho mỗi mật độ màn hình khi chạy. Ở đây là chi tiết thông tin Vector Asset Studio.

Tạo Android Project

Tạo một project android Mở build.gradle trong app module, thêm dòng code bên dưới vào khối defaultConfig .

vectorDrawables.useSupportLibrary = true

file build.gradle của chúng ta sẽ như này:

apply plugin: 'com.android.application'
 
android {
   compileSdkVersion 25
   buildToolsVersion "25.0.2"
   defaultConfig {
       applicationId "info.androidhive.vectordrawable"
       minSdkVersion 17
       targetSdkVersion 25
       versionCode 1
       versionName "1.0"
       testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
       vectorDrawables.useSupportLibrary = true
   }
   buildTypes {
       release {
           minifyEnabled false
           proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       }
   }
}
 
dependencies {
   compile fileTree(dir: 'libs', include: ['*.jar'])
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
       exclude group: 'com.android.support', module: 'support-annotations'
   })
   compile 'com.android.support:appcompat-v7:25.1.0'
   testCompile 'junit:junit:4.12'
}

nếu bạn đang sử dụng gradle version dưới 2.0 thì như bên dưới

apply plugin: 'com.android.application'

android {
   compileSdkVersion 24
   buildToolsVersion "25.0.2"
   defaultConfig {
       applicationId "info.androidhive.vectordrawable"
       minSdkVersion 17
       targetSdkVersion 24
       versionCode 1
       versionName "1.0"
       testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
       vectorDrawables.useSupportLibrary = true
       generatedDensities=[]
   }
   buildTypes {
       release {
           minifyEnabled false
           proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       }
   }
   aaptOptions {
       additionalParameters "--no-version-vectors"
   }
}

dependencies {
   compile fileTree(dir: 'libs', include: ['*.jar'])
   androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
       exclude group: 'com.android.support', module: 'support-annotations'
   })
   compile 'com.android.support:appcompat-v7:24.2.1'
   testCompile 'junit:junit:4.12'
}

Tạo VectorDrawable Từ Material Icons.

Vậy chúng ta hãy bắt đầu tạo VectorDrawables từ Material Icons (Material Icons là bộ icon chính thức từ Google đã được thiết kế dưới material design guidelines, những icon là mã nguồn mở, đẹp và dễ dàng sử dụng trong các project web, android, hay iOS). Trong Project** click chuột phải **trên thư mục drawable Đi tới New ⇒ Vector Asset

Click trên launch icon và duyệt Material Icons

Lựa chọn một icon bạn thích rồi click ok

Review name của file sau đó click **next ** Bây giờ Vector Asset Studio sẽ hiển thị vị trí về nơi file đã được save , review nó và click finish Folder drawable bây giờ bao gồm một file mới tạo và bên dưới sẽ là code của nó

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="35dp"
        android:height="35dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFe29069"
        android:pathData="M2.5,19h19v2h-19zM22.07,9.64c-0.21,-0.8 -1.04,-1.28 -1.84,-1.06L14.92,10l-6.9,-6.43 -1.93,0.51 4.14,7.17 -4.97,1.33 -1.97,-1.54 -1.45,0.39 1.82,3.16 0.77,1.33 1.6,-0.43 5.31,-1.42 4.35,-1.16L21,11.49c0.81,-0.23 1.28,-1.05 1.07,-1.85z"/>
</vector>

Bạn có thể chỉnh sửa chiều rộng (width) và chiều cao (height) của vector theo ý muốn của bạn ,bởi mặc định nó sẽ là 24dp. Một vector có thể bao gồm một hoặc nhiều path. mỗi path có thể bao gồm nhiều thuộc tính trong số đó fillColor và pathData là quan trọng nhất. fillColor là thuộc đính đinh nghĩa color của path, nó phải là một thuộc tính màu (có thể là 1 mã màu như này #aarrggbb hoặc là được trỏ tới resource color) . pathData là định nghĩa hình dạng đường. Trong trường hợp này tôi sẽ chỉnh sửa width, height, fillColor

Tạo VectorDrawable Từ SVG or PSD

Ngoài việc tạo vectorDrawable từ Material Icon chúng ta có thể tạo nó từ SVG or PSD. Tuy nhiên nó cũng có một vài hạn chế ,bạn có thể kiểm tra thêm https://developer.android.com/studio/write/vector-asset-studio.html#PSD . Trong Project click chuột phải thư mục drawable Tiếp New ⇒ Vector Asset Click trên radio button Local File (SVG, PSD) Click trên browse icon và chuyển hướng tời file SVG or PSD file lựa chọn nó Sau đó click OK Kiểm tra image trong preview và click Next ⇒ Finish. Bên dưới là file code được generate từ svg

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="100dp"
    android:height="100dp"
    android:viewportHeight="512.0"
    android:viewportWidth="512.0">
    <path
        android:fillColor="#273B7A"
        android:pathData="M256,256m-256,0a256,256 0,1 1,512 0a256,256 0,1 1,-512 0" />
    <path
        android:fillColor="#121149"
        android:pathData="M506.4,309.5L300.1,103.3l-62.2,113.4l2.3,44.8l82.5,82.5l-3.4,3.4l-35.8,-35.8l-45.6,2.9h-64.7l-66.7,105.5l83.6,83.6C211.2,509 233.2,512 256,512C379,512 481.8,425.2 506.4,309.5z" />
    <path
        android:fillColor="#FFEDB5"
        android:pathData="M401.6,290.3c-3.3,-4.6 -9.3,-6.4 -14.6,-4.4c-0.1,0 -0.2,0.1 -0.2,0.1l-89.6,29.8c0,0.7 0,1.4 -0,2.2c-0.7,11.4 -9.6,20.6 -21,21.8l-54,5.6c-3.4,0.4 -6.5,-2.1 -6.8,-5.5c-0.4,-3.4 2.1,-6.6 5.5,-6.8l54,-5.6c5.3,-0.6 9.5,-4.9 9.8,-10.2c0.2,-2.9 -0.8,-5.8 -2.7,-8c-1.9,-2.2 -4.6,-3.5 -7.6,-3.7l-71.7,-4.7c-8.1,-0.5 -16,1.3 -23.1,5.1L85,358l25.6,51.6l23.8,-20.7c10.1,-8.8 23.5,-12.6 36.7,-10.4l79.4,13.2c14.6,1.9 29.1,-1.7 41.1,-10.2l108.1,-74.5C404.5,302.8 405.4,295.5 401.6,290.3z" />
    <path
        android:fillColor="#FEE187"
        android:pathData="M274.9,327.4c5.3,-0.6 9.5,-4.9 9.8,-10.2c0.2,-2.9 -0.8,-5.8 -2.7,-8c-1.9,-2.2 -4.6,-3.5 -7.6,-3.7l-15.9,-1v24.7L274.9,327.4z" />
    <path
        android:fillColor="#FEE187"
        android:pathData="M401.6,290.3c-3.3,-4.6 -9.3,-6.4 -14.6,-4.4c-0.1,0 -0.2,0.1 -0.2,0.1l-89.6,29.8c0,0.7 0,1.4 -0,2.2c-0.7,11.4 -9.6,20.6 -21,21.8l-17.7,1.8v50.6c11.8,-0.1 23.3,-3.8 33.1,-10.7l108.1,-74.5C404.5,302.8 405.4,295.5 401.6,290.3z" />
    <path
        android:fillColor="#FFC61B"
        android:pathData="M317.4,146c0,-34.7 -28.9,-62.8 -63.9,-61.4c-31.4,1.2 -57.1,26.5 -58.9,57.9c-1.2,21.6 8.7,40.9 24.6,52.7c10.1,7.6 16.3,19.2 16.3,31.9v21.3c0,11.3 9.2,20.5 20.5,20.5l0,0c11.3,0 20.5,-9.2 20.5,-20.5V227.4c0,-12.8 6.2,-24.6 16.5,-32.3C307.8,183.9 317.4,166 317.4,146z" />
    <path
        android:fillColor="#EAA22F"
        android:pathData="M255.4,84.6v184.2c0.2,0 0.4,0 0.6,0c11.3,0 20.5,-9.2 20.5,-20.5V227.4c0,-12.8 6.2,-24.6 16.5,-32.3c14.9,-11.2 24.5,-29 24.5,-49.1C317.4,111.9 289.6,84.3 255.4,84.6z" />
    <path
        android:fillColor="#A6A8AA"
        android:pathData="M235.5,227.9v20.5c0,11.3 9.2,20.5 20.5,20.5l0,0c11.3,0 20.5,-9.2 20.5,-20.5v-20.5L235.5,227.9z" />
    <path
        android:fillColor="#808183"
        android:pathData="M255.4,227.9v40.9c0.2,0 0.4,0 0.6,0c11.3,0 20.5,-9.2 20.5,-20.5v-20.5L255.4,227.9z" />
    <path
        android:fillColor="#FF5419"
        android:pathData="M244.2,183.8c-1.1,0 -2.3,-0.3 -3.3,-1.1c-2.5,-1.8 -3,-5.3 -1.2,-7.8l17.1,-23.4H244.2c-2.1,0 -4,-1.2 -5,-3.1c-1,-1.9 -0.8,-4.1 0.5,-5.8l23.6,-32.3c1.8,-2.5 5.3,-3 7.8,-1.2c2.5,1.8 3,5.3 1.2,7.8L255.2,140.4h12.6c2.1,0 4,1.2 5,3.1c1,1.9 0.8,4.1 -0.5,5.8l-23.6,32.3C247.6,183 245.9,183.8 244.2,183.8z" />
    <path
        android:fillColor="#C92F00"
        android:pathData="M272.3,117c1.8,-2.5 1.3,-6 -1.2,-7.8c-2.5,-1.8 -6,-1.3 -7.8,1.2l-7.9,10.8v18.9L272.3,117z" />
    <path
        android:fillColor="#C92F00"
        android:pathData="M267.8,140.4h-12.4v11.2h1.4l-1.4,1.9v18.9l16.9,-23.1c1.2,-1.7 1.4,-3.9 0.5,-5.8C271.8,141.6 269.9,140.4 267.8,140.4z" />
    <path
        android:fillColor="#D35933"
        android:pathData="M66.1,355.1l32.5,-22.2l40.5,64.7l-32.5,22.2z" />
    <path
        android:fillColor="#B54324"
        android:pathData="M139.1,397.6l-20.5,-32.8l-32.4,22.5l20.4,32.6z" />
</vector>

Sử Dụng VectorDrawable

Chúng ta đã thành công trong việc thêm VectorDrawables tới project bây giờ là thời điểm sử dụng nó Mở file layout và thêm đoan code bên dưới vào file layout của bạn

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="info.androidhive.vectordrawable.MainActivity">
 
    <ImageView android:id="@+id/ic_logo"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="30dp"
        android:layout_marginTop="30dp"
        app:srcCompat="@drawable/ic_light_bulb" />
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:gravity="center_horizontal"
        android:text="Tap on icon to change tint color" />
 
    <android.support.v7.widget.AppCompatImageView
        android:id="@+id/ic_android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="30dp" />
 
    <android.support.v7.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="20dp"
        android:drawableLeft="@drawable/ic_flight_takeoff"
        android:gravity="center_horizontal"
        android:text="TextView with Vector Drawable" />
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="Radio button with vector drawable icons" />
 
    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:showDividers="middle"
        android:orientation="horizontal"
        android:gravity="center">
 
        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />
 
        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />
 
        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />
 
        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />
 
        <android.support.v7.widget.AppCompatRadioButton
            android:id="@+id/radioBtn5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@drawable/radio_selector"
            android:button="@android:color/transparent" />
 
    </RadioGroup>
 
 
</LinearLayout>

Layout ở trên sẽ tạo ra một màn hình giống như này: Sử dụng VectorDrawable với ImageView Từ xml Chúng ta hãy bắt đầu với ImageView bằng cách gắn một VectorDrawable tới ImageView thông qua xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   app:srcCompat="@drawable/ic_light_bulb"/>

Như bạn nhìn thấy , Tôi đã sử dụng app:srcCompat thay cho android:src, để cho support library làm phần còn lại là hiển thị image trên tất cả phiên bản android

Sử dụng VectorDrawable với ImageView từ Java Bây giờ chúng ta làm là gắn một VectorDrawable tới ImageView trong code java

public class MainActivity extends AppCompatActivity {
 
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        final AppCompatImageView icAndroid = (AppCompatImageView) findViewById(R.id.ic_android);
        icAndroid.setImageResource(R.drawable.ic_android);
 
        icAndroid.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Random rnd = new Random();
                int color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256));
                icAndroid.setColorFilter(color);
            }
        });
    }
}

Cho việc sử dụng VectorDrawable từ java hoặc sử dụng nó như là background you bạn khởi tạo AppCompatDelegate để cho phép compat vector từ tài nguyên.

static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

Bất kể khi nào bạn có dự định sử dụng VectorDrawable từ java hãy nhớ rằng sử dụng AppCompatView thay cho view bình thường như ở đây tôi sử dụng AppCompatImageView bây giờ gắn VectorDrawable như là src or background như bạn làm bình thường

AppCompatImageView icAndroid = (AppCompatImageView) findViewById(R.id.ic_android);
        icAndroid.setImageResource(R.drawable.ic_android);

Ngoài ra các bạn có thể tham khảo thêm 1 bài viết khác của tôi nói về Tối ưu hiệu suất của Vector Drawables Trong Android


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí