SwiftUI 框架

SwiftUI 教學:使用 SwiftUI 來打造 Search Bar 原來那麼簡單!

SwiftUI 教學:使用 SwiftUI 來打造 Search Bar 原來那麼簡單!
SwiftUI 教學:使用 SwiftUI 來打造 Search Bar 原來那麼簡單!
In: SwiftUI 框架, UIKit

最近,我收到一個問題,關於在 SwiftUI 專案中實作 Search Bar。與 UIKit 不同,SwiftUI 沒有內建的 Search Bar 物件可以使用。你或許可以使用 UIViewRepresentable 協定,以在 SwiftUI 專案中重用 UIKit 的 UISearchBar。但要使用純 SwiftUI 的方式來實作一個 Search Bar,其實並不困難。在這次的教學中,就讓我們來建立一個 SwiftUI 版的 Search Bar!

看看以下這張圖片,我們即將要打造一個這樣的 Search Bar。它看起來跟 UIKit 的 UISearchBar 沒什麼兩樣。而我們還會實作一個 Cancel 按鈕,按鈕只會在使用者開始在搜索欄打字時才會出現。

Building a Search Bar in SwiftUI 1

編者備註:如果你還不熟悉 SwiftUI,可以先閱讀我們的入門教學

實作 Search Bar UI

為了讓你專注於實作 Search Bar,你可以先下載這個初始專案,並編譯一次,以確保它執行無誤。這個 App 會顯示一個待辦事項的列表。現在,讓我們實作 SearchBar.swift 檔案來建立一個 Search Bar。

仔細觀察一下 iOS 裡面內建的標準 Search Bar,你會發現它是由一個文字輸入框 (text field) 和 Cancel 按鈕所組成的。

import SwiftUI

struct SearchBar: View {
    @Binding var text: String

    @State private var isEditing = false

    var body: some View {
        HStack {

            TextField("Search ...", text: $text)
                .padding(7)
                .padding(.horizontal, 25)
                .background(Color(.systemGray6))
                .cornerRadius(8)
                .padding(.horizontal, 10)
                .onTapGesture {
                    self.isEditing = true
                }

            if isEditing {
                Button(action: {
                    self.isEditing = false
                    self.text = ""

                }) {
                    Text("Cancel")
                }
                .padding(.trailing, 10)
                .transition(.move(edge: .trailing))
                .animation(.default)
            }
        }
    }
}

首先,我們定義了兩個變數:一個是搜尋文字的 Binding,另一個用來儲存目前搜索欄的狀態(是否正在編輯中)。

接著,我們使用了 HStack 來編排文字輸入框跟 Cancel 按鈕的位置。按鈕只會在使用者點擊了搜索欄時才會顯示。為了預覽我們實作的 Search Bar,請輸入以下的程式碼:

struct SearchBar_Previews: PreviewProvider {
    static var previews: some View {
        SearchBar(text: .constant(""))
    }
}

加入了這些程式碼之後,你應該能夠預覽整個搜索欄。點擊 Play 按鈕來測試這個搜索欄。現在,當你點擊文字輸入框之後,就會出現 Cancel 按鈕了。

swiftui-search-bar-xcode-preview

目前這個版本的 Search Bar,還缺少了兩個要素:就是 Search Icon 和 Cross Icon。我們可以在文字輸入框附加 overlay 修飾器,來加入這些 icon。將以下的程式碼放在 .cornerRadius(8) 的後面:

.overlay(
    HStack {
        Image(systemName: "magnifyingglass")
            .foregroundColor(.gray)
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
            .padding(.leading, 8)

        if isEditing {
            Button(action: {
                self.text = ""
            }) {
                Image(systemName: "multiply.circle.fill")
                    .foregroundColor(.gray)
                    .padding(.trailing, 8)
            }
        }
    }
)

我們為文字輸入框加上了兩個系統圖片,而 multiply.circle.fill 只會在使用者開始在搜索欄打字時顯示。當這個圖片被點擊時,它會將搜索欄重設成空白的狀態。你可以點擊 Play 按鈕,以在預覽視窗測試 Search Bar。

使用 Search Bar 來過濾資料

現在,我們已經準備好 Search Bar。接下來,讓我們切換到 ContentView.swift,將它加入到 list view 裡面吧。

List View 之前,加入以下的程式碼:

SearchBar(text: $searchText)
    .padding(.top, -30)

這樣,我們就功成在 title 跟 list view 之間加上了 Search Bar。
searchText 是一個狀態變數 (state variable),持有我們即將搜尋的文字。它會隨著使用者的在搜索欄所輸入的內容,來更新要搜尋的文字。

我們需要如此更新 List view 來過濾結果:

List(todoItems.filter({ searchText.isEmpty ? true : $0.name.contains(searchText) })) { item in
    Text(item.name)
}

在這段程式碼中,我們使用了 filter 函式來尋找符合搜尋文字的待辦事項。在這一段閉包中,我們先檢查了 searchText 有沒有值。如果沒有的話,我們就回傳 true,也就是會回傳全部的待辦事項。相反,如果 searchText 有值的話,就檢查待辦事項的名稱欄位是否有包含搜尋的文字。

讓我們試試執行 App 吧,結果應該會依照你所輸入的文字來找到待辦事項。

swiftui-search-bar-typing

將鍵盤收起來

如你所見,完全用 SwiftUI 打造一個 Search Bar,並不是困難的事情。可是,雖然現在它可以正常運作,但還有一個小問題需要修正。不知道你有沒有嘗試點擊 Cancel 按鈕?它的確會清除搜索欄的內容,但是虛擬鍵盤卻沒有消失。

為了修正這一點,我們需要在 Cancel 按鈕的 action block 加上一行程式碼:

// Dismiss the keyboard
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

在這一段程式碼中,我們呼叫了 sendAction 方法,來解除目前的 first responder,並收起了虛擬鍵盤。現在你可以重新執行模擬器,你會發現當你點擊 Cancel 按鈕時,它就會清除搜索欄,並且將虛擬鍵盤收起來了。

總結

在這篇教學中,我們展示了如何實作一個 Search Bar。如你所見,這個過程並不困難。如果你想深入鑽研管理資料庫內容的技巧,可以參考我們的 《精通SwiftUI》電子書。在書本中,我們會更進一步地展示如何使用 Core Data 來保留資料,以及使用 fetch request 來處理搜尋的功能,而且你還可以取得一個待辦事項 App 完整的原始碼。

你可以在這邊下載完整專案作參考。

譯者簡介:周竑翊 – 只待過新創公司的 iOS 開發者,本職是兩個兒子的爸。有空的時間喜歡看看新的技術跟科技時事。用 Playground 寫寫 Swift,但是 side project 仍然難產。其他興趣喜歡攝影、運動及看電影。歡迎寄信與我聯絡:[email protected]

原文:Building a Search Bar in SwiftUI for iPad and Mac

作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 17 App 程式設計實戰心法》、《iOS 17 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
iOS 18 新API:使用 Navigation Transition 創建 Hero 動畫式過場
SwiftUI 框架

iOS 18 新API:使用 Navigation Transition 創建 Hero 動畫式過場

Apple 的工程師可能早已認識到,許多 iOS 開發者都希望能夠重現 App Store 應用程式中的優雅 Hero 動畫。由於從頭實現這種動畫通常需要耗費大量時間與精力,Apple 在 iOS 18 SDK 中納入了這項功能。 透過這次更新,你現在只需少量的程式碼就能在自己的應用程式中實現類似的動畫過渡效果。這項重大改進讓開發者能夠創造出更具視覺吸引力且流暢的過渡效果,
如何使用 Vision APIs 從圖像中辨識文字
AI

如何使用 Vision APIs 從圖像中辨識文字

Vision 框架長期以來一直包含文字識別功能。我們已經有詳細的教程,向你展示如何使用 Vision 框架掃描圖像並執行文字識別。之前,我們使用了 VNImageRequestHandler 和 VNRecognizeTextRequest 來從圖像中提取文字。 多年來,Vision 框架已經顯著演變。在 iOS 18 中,Vision
iOS 18更新:SwiftUI 新功能介紹
SwiftUI 框架

iOS 18更新:SwiftUI 新功能介紹

SwiftUI的技術不斷演進,每次更新都讓 iOS 應用程式開發變得更加便捷。隨著 iOS 18 Beta 的推出,SwiftUI 引入了多個令人興奮的新功能,使開發者僅需幾行程式碼即可實現出色的效果。 本教學文章旨在探索這個版本中的幾項主要改進,幫助你了解如何運用這些新功能。 浮動標籤列 (Floating Tab Bar)SwiftUI中的標籤視圖(Tab
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。