+4

Custom SearchView giống với google search

I, Giới thiệu

  • Xin chào mọi người lại là mình đây. Dạo gần đây mình có làm 1 dự án có chức năng search nên tiện thể chia sẻ với mọi người luôn.
  • Mình thấy hầu hết các bài viết trên về search ở trên Google đều sử dụng RxJava của MindOrks.
  • Mình cũng dựa vào nó để làm nhưng khi thực hiện trong dự án thì lại gặp các vấn đề khó khăn khác.
  • Mình làm tutorial này để chia sẻ các case mà mình đã gặp phải từ đơn giản đến phức tạp.
  • Chú ý: thời đại architecture component rồi nên mình sẽ sử dụng AndroidX, RxJava. Comming soon: coroutine.
  • Nếu bạn thấy cái SearchView mặc định của Google không đẹp thì yên tâm hãy đọc hết bài này bạn cũng có thể tạo ra 1 cái search View dạng như Google mà chỉ bằng SearchView.
  • Phần 1: Custom SearchView. kết quả mong muốn sẽ là:

  • Let's go.

II, Thực hiện

  • Mình sẽ bỏ qua khâu import các dependecy cần thiết nhé. Mọi người phải tự tìm hiểu nhỉ.
  • Bước 1: Tạo 1 SearchView trong xml:
    <androidx.appcompat.widget.SearchView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="56dp" />
  • Đây là kết quả bạn nhận được:

  • Hai trạng thái unfocus và focus lại hiển thị 2 kiểu khác nhau. Điều này mình sẽ giải thích sau.
  • Nhìn hơi chán nhỉ 😅.
  • Bước 2: Thống nhất 1 kiểu hiển thị giữa 2 trạng thái thôi
app:iconifiedByDefault="false"
  • Kết quả là chỉ có 1 kiểu hiển thị dù nó được focus hay không

  • Bước 3: Loại bỏ submit query background:
  • Ở bước 2, chúng ta thấy 1 background được insert ở bottom của SearchView. Mình sẽ phải loại bỏ nó.
 app:queryBackground="@null"
  • Kết quả là:

  • Bước 4: Tạo cho SearchView 1 background:
  • Tạo 1 drawable trong res/drwable folder có tên là shapebgsearch.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">

    <stroke
        android:width="0.5dp"
        android:color="#000000" />

    <solid android:color="#33FFFFFF" />

    <corners
        android:bottomLeftRadius="8dp"
        android:bottomRightRadius="8dp"
        android:topLeftRadius="8dp"
        android:topRightRadius="8dp" />
</shape>
  • Các color và dimen chỉ là mình ví dụ minh họa thôi mọi người có thể thay đổi tùy ý muốn của mình nhé.
  • Và đây là kết quả:

  • Nhìn có đẹp và bắt mặt hơn rồi. Nhưng vẫn cần hoản thiện hơn nữa.
  • Bước 5 (Optional): Set search icon:
  • Dùng vector asset tool của Android studio để tạo ra 1 vector có tên là ic_menu.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="#7f000000"
        android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z" />
</vector>
  • Tiếp đó set search icon cho SearchView:
    app:searchIcon="@drawable/ic_menu"
  • Đây là kết quả:

  • Bước 6 (optional): Enable voice search:

  • Trong res/xml folder tạo file searchable.xml:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/search_hint"
    android:label="@string/app_name"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" />
  • Tiếp theo trong AndroidManifest.xml thêm vào trong thẻ <activity> của Activity chứa SearchView:
<activity android:name=".MainActivity">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>
  • Ở Acitivy hay Fragment chứa SearchView thêm:
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
search.setSearchableInfo(searchManager.getSearchableInfo(componentName))
  • Kết quả là:

  • Bước 7 (optional): Loại bỏ submit background:

  • Sau khi bạn enable voice search, nếu để ý kĩ sẽ thấy 1 background với 1 gạch nằm bên dưới của voice search. Đây là background của submit layout.

  • Để loại bỏ nó bạn thêm:

app:submitBackground="@null"
  • Và kết quả là:

III, Full xml code

  • Toàn bộ code trong xml được tổng hợp dưới đây:
<androidx.appcompat.widget.SearchView
    android:id="@+id/search"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="56dp"
    android:layout_marginEnd="16dp"
    android:background="@drawable/shape_bg_search"
    app:iconifiedByDefault="false"
    app:queryBackground="@null"
    app:searchIcon="@drawable/ic_menu"
    app:submitBackground="@null" />

IV, Giải thích (optional)

  • Mình sẽ thực hiện câu "Điều này mình sẽ giải thích sau" ở bước 1 - II nhé.
  • Mình tìm ra được những chi tiết nhỏ nhặt và ý nghĩa của SearchView: query background, submit background... là đều do mình đã xem source của nó.
  • Bấm tổ hợp shift + shift và bạn find file abcsearchview.xml: đây chính là file cấu tạo nên SearchView của chúng ta.
  • Ví dụ: LinearLayout có id = submit_area sẽ tương ứng với thuộc tính tương ứng như app:submitBackground chẳng hạn.
  • Ngoài ra bạn cũng có thể dùng SearchView#findViewById() và điền 1 id trong layout này để custom SearchView của bạn theo ý muốn.

V, Tổng kết

  • Search là 1 tác vụ phổ biến trong Android.
  • Việc custom SearchView cũng là 1 tác vụ cần thiết để UI/UX phù hợp với user.
  • Hi vọng bài viết này sẽ giúp các bạn nhiều hơn trong khi làm việc với search.
  • Những thứ nhỏ nhất là những thứ quan trọng nhất.

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í