Skip to content

Commit f2a3b7b

Browse files
authored
Add activity search to Android test app (#3275)
1 parent d409f83 commit f2a3b7b

File tree

9 files changed

+90
-8
lines changed

9 files changed

+90
-8
lines changed

platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/FeatureOverviewActivity.kt

+56-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import android.content.pm.PackageInfo
66
import android.content.pm.PackageManager
77
import android.content.res.Resources.NotFoundException
88
import android.os.Bundle
9+
import android.view.Menu
910
import android.view.View
1011
import androidx.annotation.StringRes
1112
import androidx.appcompat.app.AppCompatActivity
13+
import androidx.appcompat.widget.SearchView
1214
import androidx.lifecycle.lifecycleScope
1315
import androidx.recyclerview.widget.LinearLayoutManager
1416
import androidx.recyclerview.widget.RecyclerView
@@ -35,6 +37,7 @@ import java.util.*
3537
class FeatureOverviewActivity : AppCompatActivity() {
3638
private lateinit var recyclerView: RecyclerView
3739
private var sectionAdapter: FeatureSectionAdapter? = null
40+
private var featureAdapter: FeatureAdapter? = null
3841
private var features: List<Feature>? = null
3942

4043
override fun onCreate(savedInstanceState: Bundle?) {
@@ -50,7 +53,7 @@ class FeatureOverviewActivity : AppCompatActivity() {
5053
override fun onItemClicked(recyclerView: RecyclerView?, position: Int, view: View?) {
5154
if (sectionAdapter!!.isSectionHeaderPosition(position).not()) {
5255
val itemPosition = sectionAdapter!!.getConvertedPosition(position)
53-
val feature = features!![itemPosition]
56+
val feature = featureAdapter!!.getItem(itemPosition)
5457
startFeature(feature)
5558
}
5659
}
@@ -86,6 +89,7 @@ class FeatureOverviewActivity : AppCompatActivity() {
8689
if (featuresList.isNullOrEmpty()) {
8790
return
8891
}
92+
featureAdapter = FeatureAdapter(features!!)
8993
val sections: MutableList<FeatureSectionAdapter.Section> = ArrayList()
9094
var currentCat = ""
9195
for (i in features!!.indices) {
@@ -95,12 +99,11 @@ class FeatureOverviewActivity : AppCompatActivity() {
9599
currentCat = category
96100
}
97101
}
98-
99102
sectionAdapter = FeatureSectionAdapter(
100103
this,
101104
R.layout.section_main_layout,
102105
R.id.section_text,
103-
FeatureAdapter(features!!)
106+
featureAdapter!!
104107
)
105108
sectionAdapter!!.setSections(sections.toTypedArray())
106109
recyclerView.adapter = sectionAdapter
@@ -163,6 +166,56 @@ class FeatureOverviewActivity : AppCompatActivity() {
163166
}
164167
}
165168

169+
// Add SearchView to the app bar
170+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
171+
menuInflater.inflate(R.menu.menu_feature_overview, menu)
172+
val searchItem = menu.findItem(R.id.action_search)
173+
val searchView = searchItem.actionView as SearchView
174+
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
175+
override fun onQueryTextSubmit(query: String?): Boolean {
176+
return false // No action on submit
177+
}
178+
179+
override fun onQueryTextChange(newText: String?): Boolean {
180+
filterFeatures(newText)
181+
return true
182+
}
183+
})
184+
return true
185+
}
186+
187+
// Filter the features based on the search query
188+
private fun filterFeatures(query: String?) {
189+
val filteredFeatures = if (query.isNullOrEmpty()) {
190+
features // Show full list if query is empty
191+
} else {
192+
features?.filter { it.getLabel().contains(query, ignoreCase = true) }
193+
}
194+
updateAdapter(filteredFeatures)
195+
}
196+
197+
// Update the adapter with filtered features
198+
private fun updateAdapter(filteredFeatures: List<Feature>?) {
199+
if (filteredFeatures.isNullOrEmpty()) {
200+
featureAdapter?.update(emptyList())
201+
sectionAdapter?.setSections(emptyArray())
202+
sectionAdapter?.notifyDataSetChanged()
203+
return
204+
}
205+
val sections: MutableList<FeatureSectionAdapter.Section> = ArrayList()
206+
var currentCat = ""
207+
for (i in filteredFeatures.indices) {
208+
val category = filteredFeatures[i].category
209+
if (currentCat != category) {
210+
sections.add(FeatureSectionAdapter.Section(i, category))
211+
currentCat = category
212+
}
213+
}
214+
featureAdapter?.update(filteredFeatures)
215+
sectionAdapter?.setSections(sections.toTypedArray())
216+
sectionAdapter?.notifyDataSetChanged()
217+
}
218+
166219
companion object {
167220
private const val KEY_STATE_FEATURES = "featureList"
168221
}

platform/android/MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/adapter/FeatureAdapter.kt

+12-5
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ import org.maplibre.android.testapp.utils.FontCache
1212
/**
1313
* Adapter used for FeatureOverviewActivity.
1414
*
15-
*
1615
* Adapts a Feature to a visual representation to be shown in a RecyclerView.
17-
*
1816
*/
19-
class FeatureAdapter(private val features: List<Feature>) :
17+
class FeatureAdapter(private var features: List<Feature>) :
2018
RecyclerView.Adapter<FeatureAdapter.ViewHolder>() {
19+
2120
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
2221
var labelView: TextView
2322
var descriptionView: TextView
@@ -32,8 +31,7 @@ class FeatureAdapter(private val features: List<Feature>) :
3231
}
3332

3433
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
35-
val view =
36-
LayoutInflater.from(parent.context).inflate(R.layout.item_main_feature, parent, false)
34+
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_main_feature, parent, false)
3735
return ViewHolder(view)
3836
}
3937

@@ -45,4 +43,13 @@ class FeatureAdapter(private val features: List<Feature>) :
4543
override fun getItemCount(): Int {
4644
return features.size
4745
}
46+
47+
fun update(newFeatures: List<Feature>) {
48+
features = newFeatures
49+
notifyDataSetChanged()
50+
}
51+
52+
fun getItem(position: Int): Feature {
53+
return features[position]
54+
}
4855
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="#333333"
7+
android:alpha="0.6">
8+
<path
9+
android:fillColor="@android:color/white"
10+
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
11+
</vector>
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto">
4+
<item
5+
android:id="@+id/action_search"
6+
android:icon="@drawable/ic_search"
7+
android:title="@string/search"
8+
app:actionViewClass="androidx.appcompat.widget.SearchView"
9+
app:showAsAction="always|collapseActionView" />
10+
</menu>

platform/android/MapLibreAndroidTestApp/src/main/res/values/strings.xml

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
<string name="category_benchmark">Benchmark</string>
88
<string name="activity_benchmark_world_tour">World Tour Benchmark</string>
99
<string name="description_world_tour_benchmark">Writes out avg. fps and 1% fps after world tour with .flyTo()</string>
10+
<string name="search">Search</string>
1011
</resources>

0 commit comments

Comments
 (0)