Android AppBar配合Toolbar实现SearchView动效及适配问题
我目前正在Android平台开发搜索栏功能,实现思路参考了这篇帖子,希望在原有实现基础上扩展更多功能。上述帖子的核心实现逻辑简述如下:SearchView初始位于屏幕中部,当SearchView获取焦点时通过动画移动至屏幕顶部,失去焦点后通过动画回归初始位置。我希望实现的效果为:页面初始加载时即显示返回箭头,效果如图1所示
图1

当SearchView获取焦点时,界面需要呈现为图2所示效果
图2

我尝试编写了部分代码,但未能实现预期效果,相关代码如下:
相关代码实现
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> <!-- 可滚动内容 --> </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>
实际运行效果


预期效果
即问题开头展示的图1、图2效果。
参考实现项目:ToolbarApplication
问题更新

目前SearchView距离状态栏过近,请问该如何为其设置顶部margin或padding?
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

