Hey I am working on search bar in android. I get the lead from this post. Now I want to try something more. Above post explanation in short :- I have searchview in the middle of screen. When we focus to on searchview we animate to go to top of screen and after remove focus goes to original position of search view. Now I want to show back arrow with initial screen load, look like this
Image 1
When we focus I need to show screen like this
Image 2
I tried some piece of code, but I am not succeed
ExploreConsultationsLayoutBinding.xml
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:gravity="bottom"
android:backgroundTint="@color/red_primary_80"
android:layout_height="?attr/collapsingToolbarLayoutLargeSize"
android:fitsSystemWindows="true">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/black">
<androidx.appcompat.widget.SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginStart="16dp"
app:iconifiedByDefault="false"
android:layout_marginEnd="16dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
/>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<!-- Scrollable content -->
</androidx.coordinatorlayout.widget.CoordinatorLayout>
ExploreConsultationsActivity.kt
package com.example.app.consultation
import android.content.Context
import android.graphics.Rect
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.widget.SearchView
import com.example.app.common.BaseActivity
import com.example.app.databinding.ExploreConsultationsLayoutBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
class ExploreConsultationsActivity : BaseActivity() {
companion object {
const val CONSULTATION_LIST_KEY = "consultation_list"
}
private val binding by lazy { ExploreConsultationsLayoutBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
setupView()
}
fun setupView() {
hideActionBar()
setupSearchView()
}
fun hideActionBar() {
supportActionBar?.let { actionBar ->
actionBar.hide()
}
}
fun setupSearchView() {
binding.consultationSearchView.apply {
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?) = false
override fun onQueryTextChange(newText: String?): Boolean {
if (newText != null) {
viewModel.queryText = newText
}
return true
}
})
setOnQueryTextFocusChangeListener { view, hasFocus ->
binding.appBar.setExpanded(!hasFocus)
if (hasFocus) {
binding.toolbar.apply {
setSupportActionBar(this)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
} else {
supportActionBar?.setDisplayHomeAsUpEnabled(false)
}
isSelected = hasFocus
}
}
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (ev?.action == MotionEvent.ACTION_DOWN) {
val view: View? = currentFocus
if (view is SearchView.SearchAutoComplete) {
val outRect = Rect()
view.getGlobalVisibleRect(outRect);
if (!outRect.contains(ev.rawX.toInt(), ev.rawY.toInt())) {
view.clearFocus()
val inputMethodManager = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
return super.dispatchTouchEvent(ev)
}
}
Mainfest.xml
<activity android:name="ExploreConsultationsActivity"
android:screenOrientation="portrait"
android:theme="@style/NoActionBar"/>
Style.xml
<style name="NoActionBar" parent="@style/Theme.MaterialComponents.Light.NoActionBar">
<item name="colorPrimary">@color/abc</item>
<item name="colorPrimaryDark">@color/xyz</item>
<item name="colorAccent">@color/abc</item>
<item name="android:theme">@style/AppTheme</item>
<item name="android:colorBackground">@color/white</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="android:statusBarColor">@color/status_bar</item>
<item name="android:windowLightStatusBar" tools:ignore="NewApi">true</item>
</style>
Actual Output
Expected Output
Image 1 and Image 2 please look top image of question.
UPDATE
my search view is very close to status bar so how can I give top margin or padding?
You could change the start margin of the SearchView
when it got the focus; and return it to the original margin when it loses the focus:
var originalMargin = 0
fun setupSearchView() {
binding.consultationSearchView.apply {
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?) = false
override fun onQueryTextChange(newText: String?): Boolean {
if (newText != null) {
}
return true
}
})
val params =
binding.consultationSearchView.layoutParams as CollapsingToolbarLayout.LayoutParams
originalMargin = params.marginStart
setOnQueryTextFocusChangeListener { view, hasFocus ->
binding.appBar.setExpanded(!hasFocus)
isSelected = hasFocus
if (hasFocus)
params.marginStart = originalMargin + 150 // arbitrary constant
else
params.marginStart = originalMargin
view.layoutParams = params
}
}
}