当在searchview
中键入字符时,我无法导航到下一个片段。例如,如果我在searchview
中键入"Dog",并从Listview
中选择Dog
选项,它将引导我返回Homepage
。
但是,如果searchview
中没有任何内容,就像在searchview
中没有键入任何内容一样,则导航工作正常。例如,单击Listview
中的Dog选项将导航到Dog片段。
当不点击searchview
时,我似乎也无法使列表视图折叠。
我附上了一张图片作为我面临的问题的参考。
在下面的代码中,我使用默认的ArrayAdapter
图像参考
搜索视图.kt
//searchview
var user = arrayOf("Home","Dog","Cat","Hamster")
adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, user)
binding.categories.adapter = adapter
binding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
if (user.contains(query)) {
adapter.filter.filter(query)
} else {
Toast.makeText(this@MainActivity, "No Match found", Toast.LENGTH_LONG).show()
}
return false
}
override fun onQueryTextChange(newText: String): Boolean {
adapter.filter.filter(newText)
return false
}
})
val home = adapter.getItemId(0)
val cat = adapter.getItemId(1)
val hamster = adapter.getItemId(2)
val dog = adapter.getItemId(3)
binding.categories.setOnItemClickListener { parent, view, position, ID ->
when(ID){
home ->{navController.navigate(R.id.action_global_home2)
}
cat -> {navController.navigate(R.id.action_global_cat) }
hamster -> {navController.navigate(R.id.action_global_hamster)}
dog -> {navController.navigate(R.id.action_global_dog)
}
}
}
Searchview.xml
<androidx.drawerlayout.widget.DrawerLayout
.....
<androidx.appcompat.widget.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="30dp"
android:layout_marginBottom="16dp"
app:queryHint="Enter Search"
android:background="@drawable/searchview_background"
app:iconifiedByDefault="false"
app:queryBackground="@android:color/transparent"
>
</androidx.appcompat.widget.SearchView>
<!--Listview-->
<ListView
android:id="@+id/categories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
tools:listitem="@layout/searchview_listitem"/>
.....
<androidx.drawerlayout.widget.DrawerLayout
getItemId
对ArrayAdapter
所做的一切都是返回项目在显示列表中的位置-您可以在这个非常好的网站上查看来源:
@Override public long getItemId(int position) { return position; }
它可以用于其他适配器实现(例如,ID是项目对应的数据库行(,但在这种情况下没有。
因此,因为你正在获取原始列表,并将它们的位置存储为home
、cat
等,所以你的点击监听器最终实际上相当于:
when(position){
0 -> navController.navigate(R.id.action_global_home2)
1 -> navController.navigate(R.id.action_global_cat)
2 -> navController.navigate(R.id.action_global_hamster)
3 -> navController.navigate(R.id.action_global_dog)
}
position
与它们在显示列表中的位置有关,而不是与数据集中的位置有关。所以当你过滤";狗,并且Dog是唯一显示的项目,其position
为0。单击它,它的ID(即位置记住(与第一个分支匹配,即带您进入主页的分支。
因此,您不能真正依赖position
或默认的getItemId
实现(这是一样的(来识别您的实际项目。最简单的解决方法是获取项目本身(在本例中为String
(并与之进行比较:
when(adapter.getItem(position)){
"Home" -> navController.navigate(R.id.action_global_home2)
"Cat" -> navController.navigate(R.id.action_global_cat)
"Hamster" -> navController.navigate(R.id.action_global_hamster)
"Dog" -> navController.navigate(R.id.action_global_dog)
}
或者,如果你真的想使用索引,你可以在你的源数组中查找项目
val dataSet = user
// or you could create a list/array from inside the adapter with
// val dataSet = (0 until count).map(this::getItem)
when(dataSet.indexOf(adapter.getItem(position)){
0 -> navController.navigate(R.id.action_global_home2)
1 -> navController.navigate(R.id.action_global_cat)
2 -> navController.navigate(R.id.action_global_hamster)
3 -> navController.navigate(R.id.action_global_dog)
}
但这有点脆弱-它需要在两个不同的地方定义数据的顺序,即原始数组中的顺序和when
匹配器中的顺序。(您已经遇到了这个问题——狗和仓鼠在when
中的位置不对!(。使用String值可以确保匹配正确的项,除非您键入了错误,或者更改了原始数组中的文本,但没有更改匹配器。它们是独立的、不相连的价值观,因此没有任何保护措施。它很容易坏。
在定义数据时,最好将您的项目与标签和目的地关联起来。由于ArrayAdapter
通过对数组中包含的任何对象调用toString()
来获得它显示的字符串,因此您可以在其中放入任何内容!你可以制作一个简单的类:
class Item(val name: String, val destination: Int) {
// we only want to display the name
override fun toString() = name
}
然后用它在同一个地方定义你的数据:
val items = arrayOf(
Item("Home", R.id.action_global_home2),
Item("Cat", R.id.action_global_cat),
Item("Hamster", R.id.action_global_hamster),
Item("Dog", R.id.action_global_dog)
)
adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, items)
然后,为了处理您的点击,您只需要获取点击位置的Item
,它的导航操作就在数据中!
binding.categories.setOnItemClickListener { _, _, position, _ ->
val item = adapter.getItem(position)
item?.let { navController.navigate(it.destination) }
// or item?.destination?.run(navController::navigate) - same thing!
}
你可以在enum class
中完成所有这些,因为它是硬编码的,但这种方式允许你创建任意的Item
,从数据库或互联网等加载数据,这可能是你最终想要做的。你可以把你想要的任何数据放在Item
中,任何有用的!