1.預覽
SearchView可以在菜單欄中,也可以單獨放在頁面上,下面分開實現(實現效果圖如下:)
2.菜單欄中的SearchView
2.1新建一個menu文件
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/app_bar_search"
android:icon="@drawable/ic_search_black_24dp"
android:title="Search"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="always" />
</menu>
2.2在fragment中設置SearchView
- onCraeteView中啓用菜單
- 重載onCreateOptionsMenu方法,設置監聽事件
package com.example.ngsl.wordFragment
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.example.ngsl.R
import com.example.ngsl.room.Word
import kotlinx.android.synthetic.main.word_fragment.*
class WordFragment : Fragment() {
private lateinit var viewModel: WordViewModel
private lateinit var filterWords: LiveData<List<Word>>
private lateinit var wordFragmentAdapter: WordFragmentAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//啓用菜單欄
setHasOptionsMenu(true)
return inflater.inflate(R.layout.word_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
//創建適配器
wordFragmentAdapter = WordFragmentAdapter()
recycleView.apply {
adapter = wordFragmentAdapter
layoutManager = GridLayoutManager(requireContext(), 1)
}
//ViewModel
viewModel = ViewModelProvider(this).get(WordViewModel::class.java)
filterWords = viewModel.allWord
filterWords.observe(viewLifecycleOwner, Observer {
//爲適配器提供數據
wordFragmentAdapter.submitList(it)
})
//菜單欄相關
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
//添加菜單,R.menu.menu就是你上面創建的菜單文件
inflater.inflate(R.menu.menu, menu)
//獲取SearchView
val searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView
searchView.maxWidth = 900 //設置最大長度
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
//用戶點擊鍵盤“搜索鍵”事件
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
//用戶輸入內容發生改變事件
override fun onQueryTextChange(newText: String?): Boolean {
val pattern = newText?.trim() as String
Log.d("myLog", pattern)
filterWords.removeObservers(requireActivity())
filterWords = viewModel.searchWords(pattern)
filterWords.observe(requireActivity(), Observer {
wordFragmentAdapter.submitList(it)
})
return true
}
})
}
}
菜單欄中的SearchView,GitHub源碼鏈接:https://github.com/YDDUONG/NGSL-English(整個項目有很多組件,只看你需要的部分)
3.頁面中的SearchView
3.1我們先畫一個搜索圖標
在drawable文件夾下創建一個xml文件(ic_search.xml),寫入一下代碼
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
</vector>
3.2添加布局
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="1dp"
android:queryHint="Search Here"
app:searchIcon="@drawable/ic_search" />
3.3SearchView設置(都在註釋中了)
package com.example.gca.leftFragment.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.SearchView
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.gca.R
import com.example.gca.adapter.SearchGarbageAdapter
import com.example.gca.room.garbageTable.Garbage
import kotlinx.android.synthetic.main.search_fragment.*
/**
* A simple [Fragment] subclass.
*/
class SearchFragment : Fragment() {
private lateinit var filteredGarbage: LiveData<List<Garbage>>
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.search_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val searchViewModel = ViewModelProvider(
this,
ViewModelProvider.AndroidViewModelFactory(requireActivity().application)
).get(SearchViewModel::class.java)
//適配器
val searchGarbageAdapter = SearchGarbageAdapter() //適配器
recyclerView.apply {
adapter = searchGarbageAdapter
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
}
//觀察
filteredGarbage = searchViewModel.historyGarbageValue
filteredGarbage.observe(this.viewLifecycleOwner, Observer {
searchGarbageAdapter.submitList(it)
})
//!!!以下就是Search的設置(按需設置)
// //設置搜索框直接展開顯示。左側有放大鏡(在搜索框中) 右側有叉叉 可以關閉搜索框
// searchView.isIconified = false
// //設置搜索框直接展開顯示。左側有放大鏡(在搜索框外) 右側無叉叉 有輸入內容後有叉叉 不能關閉搜索框
// searchView.isIconifiedByDefault = false
// //設置搜索框直接展開顯示。左側有無放大鏡(在搜索框中) 右側無叉叉 有輸入內容後有叉叉 不能關閉搜索框
// searchView.onActionViewExpanded()
//其他設置
// searchView.isFocusableInTouchMode = true //設置觸摸聚焦
// searchView.requestFocus() //請求焦點
// searchView.findFocus() //獲取焦點
//這幾句就可以獲得不錯的效果
searchView.onActionViewExpanded()
searchView.isFocusable = true //設置輸入框可聚集
searchView.requestFocusFromTouch() //請求焦點
//搜索欄監聽
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
//提交監聽
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
//內容發生改變
override fun onQueryTextChange(newText: String): Boolean {
val pattern = newText.trim()
filteredGarbage.removeObservers(requireActivity())
filteredGarbage = searchViewModel.searchGarbageWithPattern(pattern)
filteredGarbage.observe(requireActivity(), Observer {
searchGarbageAdapter.submitList(it)
})
return true
}
})
}
}
4.最後,如果不想讓彈出的鍵盤擠壓佈局
修改Acticitymanifest文件
添加android:windowSoftInputMode="adjustNothing"
完整文件如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gallery">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
<activity android:name=".MainActivity"
android:windowSoftInputMode="adjustNothing">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>