# Creating a Search Experience

This is an example of creating a simple search experience using MapsIndoors. We will create a map with a search button that leads to another Fragment that handles the search and selection. On selection of a location, we go back to the map and shows the selected location on the map.

First create a Fragment or Activity with a map and MapsIndoors loaded.

We will create a Fragment that will contain a textInput field and a RecyclerView that will show a list of `MPLocations` received from the search.

```kotlin
class FullscreenSearchFragment : Fragment() {
```

As we will be using a `RecyclerView` we will need to create a `RecyclerView Adapter` to show our Location results. In this guide we will hijack the Adapter from the Template app:

```kotlin
class MPSearchItemRecyclerViewAdapter : RecyclerView.Adapter<MPSearchItemRecyclerViewAdapter.ViewHolder>() {
    private var mLocations: List<MPLocation> = ArrayList()
    private lateinit var context: Context
    private var mOnLocationSelectedListener: OnLocationSelectedListener? = null
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        context = parent.context
        return ViewHolder(FragmentSearchItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = mLocations[position]
        var iconUrl = getTypeIcon(item)
        iconUrl?.let {
            MapsIndoors.getImageProvider().loadImageAsync(it) { bitmap, error ->
                if (bitmap != null && error == null) {
                    holder.icon.setImageBitmap(bitmap)
                }
            }
        }
        holder.nameView.text = item.name
        if (item.floorName != null && item.buildingName != null) {
            val buildingName = MapsIndoors.getBuildings()?.getBuilding(item.point.latLng)?.name
            if (buildingName != null) {
                holder.subTextView.text = "Floor: " + item.floorName + " - " + buildingName
            }else {
                holder.subTextView.text = "Floor: " + item.floorName + " - " + item.buildingName
            }
        }else {
            holder.subTextView.visibility = View.GONE
        }
        holder.itemView.setOnClickListener {
            if (mOnLocationSelectedListener != null) {
                mOnLocationSelectedListener?.onLocationSelected(item)
            }
        }
    }
    private fun getTypeIcon(mpLocation: MPLocation): String? {
        MapsIndoors.getSolution()?.let {
            it.types?.forEach { type ->
                if (mpLocation.type?.equals(type.name, true) == true) {
                    return type.icon
                }
            }
        }
        return null
    }
    fun setOnLocationSelectedListener(onLocationSelectedListener: OnLocationSelectedListener) {
        mOnLocationSelectedListener = onLocationSelectedListener
    }
    override fun getItemCount(): Int = mLocations.size
    fun setLocations(locations: List<MPLocation>) {
        mLocations = locations;
    }
    fun clear() {
        mLocations = ArrayList()
        notifyDataSetChanged()
    }
    inner class ViewHolder(binding: FragmentSearchItemBinding) :
        RecyclerView.ViewHolder(binding.root) {
        val icon: ImageView = binding.locationIconView
        val nameView: TextView = binding.locationName
        val subTextView: TextView = binding.locationSubtext
        override fun toString(): String {
            return super.toString() + " '" + subTextView.text + "'"
        }
    }
}
```

Setup member variables for `FullscreenSearchFragment`:

* A RecyclerView to contain the locations
* The Adapter and LayoutManager for the RecyclerView
* Some view components

```kotlin
private lateinit var mRecyclerView: RecyclerView
private lateinit var mLinearLayoutManager: LinearLayoutManager
private val mAdapter: MPSearchItemRecyclerViewAdapter = MPSearchItemRecyclerViewAdapter()
private lateinit var searchInputTextView: TextInputEditText
private var searchHandler: Handler? = null
```

Init and setup the `RecyclerView`:

```kotlin
mRecyclerView = binding.searchList
mLinearLayoutManager = LinearLayoutManager(requireContext())
mRecyclerView.apply {
    layoutManager = mLinearLayoutManager
    adapter = mAdapter
}
```

Init and setup the view components to handle searching inside the `onViewCreated`

```kotlin
searchInputTextView = binding.searchInputEditText
val imm = requireActivity().getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
searchInputTextView.addTextChangedListener {
    searchHandler = Handler(Looper.myLooper()!!)
    searchHandler!!.postDelayed(searchRunner, 1000)
}
searchInputTextView.setOnEditorActionListener { textView, i, keyEvent ->
    if (i == EditorInfo.IME_ACTION_DONE || i == EditorInfo.IME_ACTION_SEARCH) {
        if (textView.text.isNotEmpty()) {
            search(textView.text.toString())
        }
        //Making sure keyboard is closed.
        imm.hideSoftInputFromWindow(textView.windowToken, 0)
        return@setOnEditorActionListener true
    }
    return@setOnEditorActionListener false
}
```

create a Runnable to execute a search

```kotlin
private val searchRunner: Runnable = Runnable {
    val text = searchInputTextView.text
    if (text?.length!! >= 2) {
        search(text.toString())
    }
}
```

Add a listener to the Adapter for when a user selects a location, to navigate back to the map and show the selected location. Here we use navigation together with a bundle to tell the other fragment of the selected location

```kotlin
mAdapter.setOnLocationSelectedListener { location ->
    if (location != null) {
        val bundle = Bundle()
        bundle.putString("locationId", location.locationId)
        findNavController().navigate(R.id.action_nav_search_fullscreen_to_nav_search, bundle)
        return@setOnLocationSelectedListener true
    }
    return@setOnLocationSelectedListener false
}
```

[See the sample in FullscreenSearchFragment.kt](https://github.com/MapsPeople/MapsIndoors-Android-Examples/blob/main/MapsIndoorsSamples/app/src/main/java/com/mapspeople/mapsindoorssamples/ui/search/FullscreenSearchFragment.kt) Now we will implement the `FullscreenSearchFragment` together with our Fragment or Activity containing a MapsIndoors Map. Add a Button to open the `FullscreenSearchFragment` inside your Activity or Fragment view and a assign a Click listener to it.

```kotlin
binding.searchButton.setOnClickListener {
    openSearchFragment()
}
```

Create the `openSearchFragment` method to navigate to the `FullScreenSearchFragment`

```kotlin
private fun openSearchFragment() {
    val navController = findNavController()
    navController.navigate(R.id.action_nav_search_to_nav_search_fullscreen)
}
```

Finally create a way to handle the selected location when a user is navigated to your fragment again. How this example is set up the Map will be reloaded when navigated to it. Therefor we will handle the selection after `MapControl` is created.

```kotlin
MapControl.create(mapConfig) { mapControl: MapControl?, miError: MIError? ->
    mMapControl = mapControl
    //Enable Live Data on the map
    if (miError == null) {
        var locationId = arguments?.get("locationId") as String?
        if (locationId != null) {
            mMapControl?.selectLocation(locationId, MPSelectionBehavior.DEFAULT)
        }else {
            //No errors so getting the first venue (in the white house solution the only one)
            val venue = MapsIndoors.getVenues()?.defaultVenue
            activity?.runOnUiThread {
                if (venue != null) {
                    //Animates the camera to fit the new venue
                    mMap!!.animateCamera(
                        CameraUpdateFactory.newLatLngBounds(
                            LatLngBoundsConverter.toLatLngBounds(venue.bounds!!),
                            19
                        )
                    )
                }
            }
        }
    }
}
```

[See the sample in SearchFragment.kt](https://github.com/MapsPeople/MapsIndoors-Android-Examples/blob/main/MapsIndoorsSamples/app/src/main/java/com/mapspeople/mapsindoorssamples/ui/search/SearchFragment.kt)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mapsindoors.com/sdks-and-frameworks/android/searching/creating-a-search-experience.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
