Page Menu
Home
GitPull.it
Search
Configure Global Search
Log In
Files
F11576606
D173.1774536880.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
16 KB
Referenced Files
None
Subscribers
None
D173.1774536880.diff
View Options
diff --git a/app/src/main/java/it/reyboz/bustorino/adapters/StringListAdapter.kt b/app/src/main/java/it/reyboz/bustorino/adapters/StringListAdapter.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/adapters/StringListAdapter.kt
@@ -0,0 +1,32 @@
+package it.reyboz.bustorino.adapters
+
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+
+class StringListAdapter(private val stringList: List<String>) :
+ RecyclerView.Adapter<StringListAdapter.StringViewHolder>() {
+
+ // ViewHolder class to hold the TextView for each item
+ class StringViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ val textView: TextView = itemView.findViewById(android.R.id.text1)
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StringViewHolder {
+ // Inflate the layout for each item in the RecyclerView (simple_list_item_1)
+ val view = LayoutInflater.from(parent.context)
+ .inflate(android.R.layout.simple_list_item_1, parent, false)
+ return StringViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: StringViewHolder, position: Int) {
+ // Bind the string from stringList at this position to the TextView
+ holder.textView.text = stringList[position]
+ }
+
+ override fun getItemCount(): Int = stringList.size
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt
@@ -3,19 +3,22 @@
import android.content.Context
import android.os.Bundle
import android.util.Log
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
+import android.view.*
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import android.widget.ImageView
import android.widget.TextView
+import androidx.appcompat.widget.SearchView
+import androidx.core.view.MenuHost
+import androidx.core.view.MenuProvider
import androidx.fragment.app.viewModels
+import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.RecyclerView
import it.reyboz.bustorino.R
import it.reyboz.bustorino.adapters.RouteAdapter
import it.reyboz.bustorino.adapters.RouteOnlyLineAdapter
+import it.reyboz.bustorino.adapters.StringListAdapter
import it.reyboz.bustorino.backend.utils
import it.reyboz.bustorino.data.PreferencesHolder
import it.reyboz.bustorino.data.gtfs.GtfsRoute
@@ -40,6 +43,7 @@
private lateinit var urbanLinesTitle: TextView
private lateinit var extrurbanLinesTitle: TextView
private lateinit var touristLinesTitle: TextView
+ //private lateinit var searchBar: SearchView
private var routesByAgency = HashMap<String, ArrayList<GtfsRoute>>()
@@ -61,6 +65,8 @@
}
private val arrows = HashMap<String, ImageView>()
private val durations = HashMap<String, Long>()
+ //private val recyclerViewAdapters= HashMap<String,RouteAdapter >()
+ private val lastQueryEmptyForAgency = HashMap<String, Boolean>(3)
private var openRecyclerView = "AG_URBAN"
override fun onCreateView(
@@ -78,7 +84,6 @@
urbanLinesTitle = rootView.findViewById(R.id.urbanLinesTitleView)
extrurbanLinesTitle = rootView.findViewById(R.id.extraurbanLinesTitleView)
touristLinesTitle = rootView.findViewById(R.id.touristLinesTitleView)
-
arrows[AG_URBAN] = rootView.findViewById(R.id.arrowUrb)
arrows[AG_TOUR] = rootView.findViewById(R.id.arrowTourist)
arrows[AG_EXTRAURB] = rootView.findViewById(R.id.arrowExtraurban)
@@ -101,29 +106,42 @@
favoritesRecyclerView.layoutManager = gridLayoutManager
- viewModel.routesLiveData.observe(viewLifecycleOwner){
+ viewModel.getLinesLiveData().observe(viewLifecycleOwner){
//routesList = ArrayList(it)
//routesList.sortWith(linesComparator)
routesByAgency.clear()
+ for (k in AGENCIES){
+ routesByAgency[k] = ArrayList()
+ }
for(route in it){
val agency = route.agencyID
- if(!routesByAgency.containsKey(agency)){
- routesByAgency[agency] = ArrayList()
+ if(agency !in routesByAgency.keys){
+ Log.e(DEBUG_TAG, "The agency $agency is not present in the predefined agencies (${routesByAgency.keys})")
}
routesByAgency[agency]?.add(route)
-
}
- //val adapter = RouteOnlyLineAdapter(routesByAgency.map { route-> route.shortName })
//zip agencies and recyclerviews
Companion.AGENCIES.zip(recViews) { ag, recView ->
routesByAgency[ag]?.let { routeList ->
- routeList.sortWith(linesComparator)
- //val adapter = RouteOnlyLineAdapter(it.map { rt -> rt.shortName })
- val adapter = RouteAdapter(routeList,routeClickListener)
- recView.adapter = adapter
+ if (routeList.size > 0) {
+ routeList.sortWith(linesComparator)
+ //val adapter = RouteOnlyLineAdapter(it.map { rt -> rt.shortName })
+ val adapter = RouteAdapter(routeList, routeClickListener)
+ val lastQueryEmpty = if(ag in lastQueryEmptyForAgency.keys) lastQueryEmptyForAgency[ag]!! else true
+ if (lastQueryEmpty)
+ recView.adapter = adapter
+ else recView.swapAdapter(adapter, false)
+ lastQueryEmptyForAgency[ag] = false
+ } else {
+ val messageString = if(viewModel.getLineQueryValue().isNotEmpty()) getString(R.string.no_lines_found_query) else getString(R.string.no_lines_found)
+ val extraAdapter = StringListAdapter(listOf(messageString))
+ recView.adapter = extraAdapter
+ lastQueryEmptyForAgency[ag] = true
+
+ }
durations[ag] = if(routeList.size < 20) ViewUtils.DEF_DURATION else 1000
}
}
@@ -164,6 +182,54 @@
return rootView
}
+ fun setUserSearch(textSearch:String){
+ viewModel.setLineQuery(textSearch)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ val menuHost: MenuHost = requireActivity()
+
+ // Add menu items without using the Fragment Menu APIs
+ // Note how we can tie the MenuProvider to the viewLifecycleOwner
+ // and an optional Lifecycle.State (here, RESUMED) to indicate when
+ // the menu should be visible
+ menuHost.addMenuProvider(object : MenuProvider {
+ override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
+ // Add menu items here
+ menuInflater.inflate(R.menu.menu_search, menu)
+
+ val search = menu.findItem(R.id.searchMenuItem).actionView as SearchView
+ search.setOnQueryTextListener(object : SearchView.OnQueryTextListener{
+ override fun onQueryTextSubmit(query: String?): Boolean {
+ setUserSearch(query ?: "")
+ return true
+ }
+
+ override fun onQueryTextChange(query: String?): Boolean {
+ setUserSearch(query ?: "")
+ return true
+ }
+
+ })
+
+ search.queryHint = getString(R.string.search_box_lines_suggestion_filter)
+ }
+
+ override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
+ // Handle the menu selection
+ if (menuItem.itemId == R.id.searchMenuItem){
+ Log.d(DEBUG_TAG, "Clicked on search menu")
+ }
+ else{
+ Log.d(DEBUG_TAG, "Clicked on something else")
+ }
+ return false
+ }
+ }, viewLifecycleOwner, Lifecycle.State.RESUMED)
+ }
+
+
private fun closeOpenFavorites(){
if(favoritesRecyclerView.visibility == View.VISIBLE){
//close it
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/ScreenBaseFragment.java b/app/src/main/java/it/reyboz/bustorino/fragments/ScreenBaseFragment.java
--- a/app/src/main/java/it/reyboz/bustorino/fragments/ScreenBaseFragment.java
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/ScreenBaseFragment.java
@@ -3,6 +3,7 @@
import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
+import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt
@@ -1,7 +1,10 @@
package it.reyboz.bustorino.viewmodels
import android.app.Application
+import android.util.Log
import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map
@@ -12,15 +15,14 @@
class LinesGridShowingViewModel(application: Application) : AndroidViewModel(application) {
- private val gtfsRepo: GtfsRepository
-
- init {
- val gtfsDao = GtfsDatabase.getGtfsDatabase(application).gtfsDao()
- gtfsRepo = GtfsRepository(gtfsDao)
-
+ private val linesNameSorter = LinesNameSorter()
+ private val linesComparator = Comparator<GtfsRoute> { a,b ->
+ return@Comparator linesNameSorter.compare(a.shortName, b.shortName)
}
- val routesLiveData = gtfsRepo.getAllRoutes()
+ private val gtfsRepo: GtfsRepository
+
+ private val routesLiveData: LiveData<List<GtfsRoute>> //= gtfsRepo.getAllRoutes()
val isUrbanExpanded = MutableLiveData(true)
val isExtraUrbanExpanded = MutableLiveData(false)
@@ -29,15 +31,45 @@
val favoritesLinesIDs = MutableLiveData<HashSet<String>>()
- private val linesNameSorter = LinesNameSorter()
- private val linesComparator = Comparator<GtfsRoute> { a,b ->
- return@Comparator linesNameSorter.compare(a.shortName, b.shortName)
+ private val queryLiveData = MutableLiveData("")
+ fun setLineQuery(query: String){
+ if(query!=queryLiveData.value)
+ queryLiveData.value = query
+ }
+ fun getLineQueryValue():String{
+ return queryLiveData.value ?: ""
+ }
+ private val filteredLinesLiveData = MediatorLiveData<List<GtfsRoute>>()
+ fun getLinesLiveData(): LiveData<List<GtfsRoute>> {
+ return filteredLinesLiveData
+ }
+
+ private fun filterLinesForQuery(lines: List<GtfsRoute>, query: String): List<GtfsRoute>{
+ val result= lines.filter { r-> query.lowercase() in r.shortName.lowercase() }
+
+ return result
+ }
+
+ init {
+ val gtfsDao = GtfsDatabase.getGtfsDatabase(application).gtfsDao()
+ gtfsRepo = GtfsRepository(gtfsDao)
+ routesLiveData = gtfsRepo.getAllRoutes()
+
+ filteredLinesLiveData.addSource(routesLiveData){
+ filteredLinesLiveData.value = filterLinesForQuery(it,queryLiveData.value ?: "" )
+ }
+ filteredLinesLiveData.addSource(queryLiveData){
+ routesLiveData.value?.let { routes ->
+ filteredLinesLiveData.value = filterLinesForQuery(routes, it)
+ }
+ }
}
fun setFavoritesLinesIDs(linesIds: HashSet<String>){
favoritesLinesIDs.value = linesIds
}
+
val favoritesLines = favoritesLinesIDs.map {lineIds ->
val linesList = ArrayList<GtfsRoute>()
if (lineIds.size == 0 || routesLiveData.value==null) return@map linesList
diff --git a/app/src/main/res/drawable/magnifying_glass.xml b/app/src/main/res/drawable/magnifying_glass.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/magnifying_glass.xml
@@ -0,0 +1,8 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true"
+ android:height="28dp" android:viewportHeight="16"
+ android:viewportWidth="16" android:width="28dp">
+
+ <path android:fillColor="?attr/colorOnPrimary"
+ android:pathData="M13.073,12.291 L10.147,9.364a3.971,3.971 0,1 0,-0.783 0.783l2.927,2.927ZM7.009,9.839A2.829,2.829 0,1 1,9.839 7.009,2.833 2.833,0 0,1 7.009,9.839Z"/>
+
+</vector>
diff --git a/app/src/main/res/layout/fragment_lines_grid.xml b/app/src/main/res/layout/fragment_lines_grid.xml
--- a/app/src/main/res/layout/fragment_lines_grid.xml
+++ b/app/src/main/res/layout/fragment_lines_grid.xml
@@ -37,7 +37,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/arrowFavorites"
app:layout_constraintBottom_toTopOf="@id/favoritesRecyclerView"
- android:layout_marginLeft="6dp"
+ android:layout_marginStart="6dp"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintVertical_chainStyle="packed"/>
<androidx.recyclerview.widget.RecyclerView
@@ -171,6 +171,7 @@
app:layout_constraintVertical_bias="0.0"
/>
+
</androidx.constraintlayout.widget.ConstraintLayout>
<!--</androidx.core.widget.NestedScrollView>-->
</FrameLayout>
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_search.xml b/app/src/main/res/menu/menu_search.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/menu/menu_search.xml
@@ -0,0 +1,11 @@
+<?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/searchMenuItem"
+ android:title="@string/search"
+ android:icon="@drawable/magnifying_glass"
+ app:actionViewClass="androidx.appcompat.widget.SearchView"
+ app:showAsAction="collapseActionView|ifRoom"/>
+
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -26,6 +26,9 @@
<string name="extraurban_lines">Linee extraurbane</string>
<string name="turist_lines">Linee turistiche</string>
<string name="direction_duep">Direzione:</string>
+ <string name="no_lines_found">Nessuna linea in questa categoria</string>
+ <string name="no_lines_found_query">Nessuna linea corrisponde alla ricerca</string>
+ <string name="search_box_lines_suggestion_filter">Filtra per nome</string>
<string name="line_fill">Linea: %1$s</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -38,6 +38,9 @@
<string name="urban_lines">Urban lines</string>
<string name="extraurban_lines">Extra urban lines</string>
<string name="turist_lines">Tourist lines</string>
+ <string name="no_lines_found">No lines found in this category</string>
+ <string name="no_lines_found_query">No lines match the searched name</string>
+
<string name="direction_duep">Destination:</string>
<string name="lines_fill">Lines: %1$s</string>
@@ -245,6 +248,7 @@
<string name="donate_now">Buy us a coffee</string>
<string name="map">Map</string>
<string name="stop_search_view_title">Search by stop</string>
+ <string name="search_box_lines_suggestion_filter">Filter by name</string>
<string name="requesting_db_update">Launching database update</string>
<string name="downloading_data_mato">Downloading data from MaTO server</string>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 26, 15:54 (13 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1774433
Default Alt Text
D173.1774536880.diff (16 KB)
Attached To
Mode
D173: Add search of lines functionality in-app
Attached
Detach File
Event Timeline
Log In to Comment