Skip to content

Commit 8db9bb3

Browse files
author
LeanBitLab
committed
feat(settings): add unified global search bar across all settings tabs
- Move search input to the root of the scroll view above all tabs - Filter across all categories (Style, Content, Reorder, System) in real-time - Temporarily expand tabs during active search for a seamless unified view - Automatically restore tab views and category headers when search is cleared
1 parent 060a60c commit 8db9bb3

2 files changed

Lines changed: 107 additions & 47 deletions

File tree

‎app/src/main/java/com/leanbitlab/lwidget/MainActivity.kt‎

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class MainActivity : AppCompatActivity() {
192192
setupSections()
193193
setupPreviewWallpaper()
194194
setupTabLayout()
195-
setupContentSearch()
195+
setupGlobalSettingsSearch()
196196
updateLivePreview()
197197

198198
// Advanced Section
@@ -337,6 +337,10 @@ class MainActivity : AppCompatActivity() {
337337

338338
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
339339
override fun onTabSelected(tab: TabLayout.Tab) {
340+
val searchInput = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.search_settings_input)
341+
if (!searchInput?.text.isNullOrEmpty()) {
342+
searchInput?.setText("")
343+
}
340344
prefs.edit().putInt("selected_settings_tab", tab.position).apply()
341345
tabContainers.forEachIndexed { index, container ->
342346
container?.visibility = if (index == tab.position) View.VISIBLE else View.GONE
@@ -2238,38 +2242,91 @@ class MainActivity : AppCompatActivity() {
22382242
sendBroadcast(intent)
22392243
}
22402244

2241-
private fun setupContentSearch() {
2242-
val searchInput = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.search_content_input) ?: return
2245+
private fun setupGlobalSettingsSearch() {
2246+
val searchInput = findViewById<com.google.android.material.textfield.TextInputEditText>(R.id.search_settings_input) ?: return
2247+
val tabContainers = listOf(
2248+
findViewById<View>(R.id.container_tab_style),
2249+
findViewById<View>(R.id.container_tab_content),
2250+
findViewById<View>(R.id.container_tab_layout),
2251+
findViewById<View>(R.id.container_tab_system)
2252+
)
2253+
val tabLayout = findViewById<com.google.android.material.tabs.TabLayout>(R.id.tab_layout)
2254+
22432255
val cardMap = mapOf(
2244-
R.id.card_time to listOf("time", "clock"),
2245-
R.id.card_next_alarm to listOf("alarm", "next alarm"),
2246-
R.id.card_world_clock to listOf("world clock", "timezone", "time zone"),
2247-
R.id.card_date to listOf("date", "calendar"),
2248-
R.id.card_battery to listOf("battery"),
2249-
R.id.card_temp to listOf("temperature", "temp"),
2250-
R.id.card_weather to listOf("weather", "forecast", "breezy"),
2251-
R.id.card_data to listOf("data", "data usage", "cellular"),
2252-
R.id.card_storage to listOf("storage", "internal storage", "disk"),
2253-
R.id.card_ram to listOf("ram", "memory"),
2254-
R.id.card_steps to listOf("steps", "step counter", "activity", "fitness"),
2255-
R.id.card_screen_time to listOf("screen time", "usage"),
2256-
R.id.card_events to listOf("events", "calendar", "agenda"),
2257-
R.id.card_tasks to listOf("tasks", "tasks.org", "todo")
2256+
// Style Tab
2257+
R.id.card_appearance_presets to listOf("presets", "themes", "minimal", "neon", "cockpit", "sunset", "monochrome", "snowfall"),
2258+
R.id.card_appearance_outline to listOf("outline", "border", "stroke", "outline color", "stroke width"),
2259+
R.id.card_appearance_colors to listOf("colors", "dynamic colors", "text color", "background color", "custom colors", "rgb"),
2260+
R.id.card_appearance_theme to listOf("theme", "dark mode", "light mode", "system theme", "mode"),
2261+
R.id.card_appearance_font to listOf("font", "typeface", "typography", "serif", "mono", "monospace", "cursive", "condensed", "thin", "light", "bold"),
2262+
R.id.card_appearance_transparency to listOf("transparency", "opacity", "background opacity", "alpha"),
2263+
R.id.card_appearance_padding to listOf("padding", "margin", "spacing", "inset"),
2264+
2265+
// Content Tab
2266+
R.id.card_time to listOf("time", "clock", "hour", "format", "12-hour", "24-hour", "clock app"),
2267+
R.id.card_next_alarm to listOf("alarm", "next alarm", "upcoming alarm"),
2268+
R.id.card_world_clock to listOf("world clock", "timezone", "time zone", "utc"),
2269+
R.id.card_date to listOf("date", "calendar", "day", "month"),
2270+
R.id.card_battery to listOf("battery", "percentage", "charging", "battery level"),
2271+
R.id.card_temp to listOf("temperature", "temp", "battery temp", "celsius", "fahrenheit"),
2272+
R.id.card_weather to listOf("weather", "forecast", "breezy", "condition", "breezy weather"),
2273+
R.id.card_data to listOf("data", "data usage", "cellular", "wifi", "network"),
2274+
R.id.card_storage to listOf("storage", "internal storage", "disk", "free space"),
2275+
R.id.card_ram to listOf("ram", "memory", "free ram", "ram usage"),
2276+
R.id.card_steps to listOf("steps", "step counter", "activity", "fitness", "pedometer", "walking"),
2277+
R.id.card_screen_time to listOf("screen time", "usage", "digital wellbeing"),
2278+
R.id.card_events to listOf("events", "calendar", "agenda", "calendar app", "schedule"),
2279+
R.id.card_tasks to listOf("tasks", "tasks.org", "todo", "to-do", "task list"),
2280+
2281+
// Layout Tab
2282+
R.id.card_appearance_reorder to listOf("reorder", "order", "column", "layout", "arrange", "drag", "stack"),
2283+
2284+
// System Tab
2285+
R.id.card_language to listOf("language", "locale", "translation", "languages"),
2286+
R.id.card_advanced to listOf("advanced", "keep alive", "battery optimization", "foreground service", "service", "backup", "export", "import"),
2287+
R.id.card_permissions to listOf("permissions", "calendar permission", "usage stats", "activity recognition", "notifications"),
2288+
R.id.card_about to listOf("about", "version", "github", "source code", "developer", "license", "privacy", "author"),
2289+
R.id.card_changelog to listOf("changelog", "whats new", "updates", "history")
2290+
)
2291+
2292+
val headerLabels: List<View> = listOfNotNull(
2293+
findViewById(R.id.label_category_content),
2294+
findViewById(R.id.label_category_stats)
22582295
)
22592296

22602297
searchInput.addTextChangedListener(object : android.text.TextWatcher {
22612298
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
22622299
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
22632300
override fun afterTextChanged(s: android.text.Editable?) {
22642301
val query = s?.toString()?.trim()?.lowercase() ?: ""
2265-
for ((cardId, keywords) in cardMap) {
2266-
val card = findViewById<View>(cardId) ?: continue
2267-
if (query.isEmpty()) {
2268-
card.visibility = View.VISIBLE
2269-
} else {
2302+
val isSearching = query.isNotEmpty()
2303+
2304+
if (isSearching) {
2305+
// Make all tab containers visible so search shows matches across all categories
2306+
tabContainers.forEach { container -> container?.visibility = View.VISIBLE }
2307+
tabLayout?.visibility = View.GONE
2308+
2309+
for ((cardId, keywords) in cardMap) {
2310+
val card = findViewById<View>(cardId) ?: continue
22702311
val matches = keywords.any { it.contains(query) }
22712312
card.visibility = if (matches) View.VISIBLE else View.GONE
22722313
}
2314+
headerLabels.forEach { label ->
2315+
label.visibility = View.GONE
2316+
}
2317+
} else {
2318+
// Restore tabs and active container
2319+
tabLayout?.visibility = View.VISIBLE
2320+
val selectedTab = tabLayout?.selectedTabPosition?.coerceIn(0, 3) ?: 0
2321+
tabContainers.forEachIndexed { index, container ->
2322+
container?.visibility = if (index == selectedTab) View.VISIBLE else View.GONE
2323+
}
2324+
for ((cardId, _) in cardMap) {
2325+
findViewById<View>(cardId)?.visibility = View.VISIBLE
2326+
}
2327+
headerLabels.forEach { label ->
2328+
label.visibility = View.VISIBLE
2329+
}
22732330
}
22742331
}
22752332
})

‎app/src/main/res/layout/activity_main.xml‎

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,32 @@
169169
android:clipToPadding="false"
170170
android:paddingBottom="80dp">
171171

172+
<!-- GLOBAL SETTINGS SEARCH -->
173+
<com.google.android.material.textfield.TextInputLayout
174+
android:id="@+id/search_settings_layout"
175+
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
176+
android:layout_width="match_parent"
177+
android:layout_height="wrap_content"
178+
android:layout_marginTop="4dp"
179+
android:layout_marginBottom="12dp"
180+
app:boxCornerRadiusTopStart="24dp"
181+
app:boxCornerRadiusTopEnd="24dp"
182+
app:boxCornerRadiusBottomStart="24dp"
183+
app:boxCornerRadiusBottomEnd="24dp"
184+
app:startIconDrawable="@drawable/ic_search"
185+
app:endIconMode="clear_text"
186+
android:hint="@string/search_settings_hint">
187+
188+
<com.google.android.material.textfield.TextInputEditText
189+
android:id="@+id/search_settings_input"
190+
android:layout_width="match_parent"
191+
android:layout_height="wrap_content"
192+
android:inputType="text"
193+
android:imeOptions="actionDone"
194+
android:maxLines="1"
195+
android:textSize="14sp" />
196+
</com.google.android.material.textfield.TextInputLayout>
197+
172198
<!-- TAB 1: STYLE -->
173199
<LinearLayout
174200
android:id="@+id/container_tab_style"
@@ -773,6 +799,7 @@
773799

774800
<!-- CATEGORY: CONTENT -->
775801
<TextView
802+
android:id="@+id/label_category_content"
776803
android:layout_width="wrap_content"
777804
android:layout_height="wrap_content"
778805
android:text="@string/category_content"
@@ -783,31 +810,6 @@
783810
android:layout_marginTop="8dp"
784811
android:layout_marginBottom="4dp"/>
785812

786-
<!-- SEARCH / FILTER CONTENT -->
787-
<com.google.android.material.textfield.TextInputLayout
788-
android:id="@+id/search_content_layout"
789-
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
790-
android:layout_width="match_parent"
791-
android:layout_height="wrap_content"
792-
android:layout_marginTop="4dp"
793-
android:layout_marginBottom="12dp"
794-
app:boxCornerRadiusTopStart="24dp"
795-
app:boxCornerRadiusTopEnd="24dp"
796-
app:boxCornerRadiusBottomStart="24dp"
797-
app:boxCornerRadiusBottomEnd="24dp"
798-
app:startIconDrawable="@drawable/ic_search"
799-
app:endIconMode="clear_text"
800-
android:hint="@string/search_settings_hint">
801-
802-
<com.google.android.material.textfield.TextInputEditText
803-
android:id="@+id/search_content_input"
804-
android:layout_width="match_parent"
805-
android:layout_height="wrap_content"
806-
android:inputType="text"
807-
android:imeOptions="actionDone"
808-
android:maxLines="1"
809-
android:textSize="14sp" />
810-
</com.google.android.material.textfield.TextInputLayout>
811813

812814
<!-- FEATURE: Time -->
813815
<com.google.android.material.card.MaterialCardView
@@ -999,6 +1001,7 @@
9991001

10001002
<!-- CATEGORY: STATS -->
10011003
<TextView
1004+
android:id="@+id/label_category_stats"
10021005
android:layout_width="wrap_content"
10031006
android:layout_height="wrap_content"
10041007
android:text="@string/category_stats"

0 commit comments

Comments
 (0)