返回

Android SearchView 布局调整与 Fragment 数据过滤方案

Android

Android SearchView 布局调整及 Fragment 数据过滤

当在 Android 应用中使用带自定义 Toolbar 的 Activity 和 Fragment 实现 SearchView 时,一个常见的问题是点击搜索图标后 Toolbar 尺寸发生变化,这通常与导航栏和其他布局元素相互作用有关。 本文将探讨该问题的成因,并提供几种解决方案。

问题分析

Toolbar 尺寸变化的原因通常在于以下几点:

  1. 导航栏的影响 :如果 Activity 中使用了导航栏,Toolbar 的高度可能会受到导航栏显示或隐藏状态的影响。当搜索栏展开时,系统可能会调整 Toolbar 的高度以适应导航栏和搜索栏同时显示的需求。

  2. AppBarLayout 的布局行为 :AppBarLayout 作为 Toolbar 的容器,其布局行为会影响 Toolbar 的最终尺寸。AppBarLayout 的 layout_scrollFlags 属性定义了 Toolbar 在滚动事件中的行为,例如 scrollenterAlwaysenterAlwaysCollapsed 等。不恰当的 layout_scrollFlags 设置可能导致 Toolbar 在搜索栏展开时尺寸异常。

  3. SearchView 的布局参数 :SearchView 自身的布局参数,如 maxWidthlayout_width 等,也会影响 Toolbar 的尺寸。如果 SearchView 宽度设置为 match_parentwrap_content,可能会导致 Toolbar 拉伸以适应 SearchView 的宽度。

解决方案

以下是几种解决 SearchView 导致 Toolbar 尺寸变化的方案。

方案一: 调整 AppBarLayout 的 layout_scrollFlags

AppBarLayout 的 layout_scrollFlags 属性可以控制 Toolbar 在滚动时的行为。 使用合适的 layout_scrollFlags 可以避免 Toolbar 尺寸的异常变化。

  • 原理: 通过设置AppBarLayout 的 layout_scrollFlagsscroll|enterAlways|snap ,让Toolbar在展开SearchView的时候保持固定的高度,而不是被SearchView撑开。

  • 操作步骤:

    1. 打开 Activity 的布局文件(activity.xml)。
    2. 找到包含 AppBarLayout 标签的代码段。
    3. AppBarLayoutlayout_scrollFlags 属性设置为 scroll|enterAlways|snap
  • 代码示例:

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:elevation="5dp"
        app:layout_scrollFlags="scroll|enterAlways|snap">
       <!-- Toolbar 代码 -->
    </android.support.design.widget.AppBarLayout>
    

方案二:固定 Toolbar 高度

直接为 Toolbar 设置固定高度,可以防止其尺寸因 SearchView 展开而变化。但这种方式可能会限制 Toolbar 在不同屏幕尺寸和配置下的适应性。

  • 原理: 通过设置Toolbar的固定高度来约束Toolbar大小变化

  • 操作步骤:

    1. 打开 Activity 的布局文件 (activity.xml).
    2. 找到 Toolbar 标签。
    3. 添加 android:layout_height 属性,并指定一个固定的高度值,例如 ?attr/actionBarSize 或具体的 dp 值,如 56dp
  • 代码示例:

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        style="@style/Toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:contentInsetEnd="5dp"
       <!--  其他Toolbar属性-->
       >
        <!-- Toolbar 内部布局 -->
    </android.support.v7.widget.Toolbar>
    

方案三: 动态调整 SearchView 宽度

在 SearchView 展开时,动态调整其宽度,避免其宽度撑满 Toolbar。可以设置一个合适的 maxWidth 值,或者在 SearchView 展开和收缩时动态修改其宽度。

  • 原理: 通过设置 SearchView 的最大宽度或者在运行时动态调整其宽度,防止 SearchView 撑满 Toolbar。

  • 操作步骤:

    1. 在 Fragment 的 onCreateOptionsMenu 方法中,找到 SearchView 的初始化代码。
    2. 在 SearchView 初始化完成后,调用 setMaxWidth() 方法设置最大宽度,或者使用 setOnActionExpandListener 监听 SearchView 的展开状态,动态设置宽度。
  • 代码示例:

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        getBaseActivity().getMenuInflater().inflate(R.menu.menu_main, menu);
        SearchView searchView;
        SearchManager searchManager = (SearchManager) getBaseActivity().getSystemService(Context.SEARCH_SERVICE);
        searchView = menu.findItem(R.id.action_search).getActionView();
    
       if(searchManager !=null){
            searchView.setSearchableInfo(searchManager.getSearchableInfo(getBaseActivity().getComponentName()));
            MenuItem searchMenuItem = menu.findItem(R.id.action_search);
            searchMenuItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
                  @Override
                 public boolean onMenuItemActionExpand(MenuItem item) {
                    searchView.setMaxWidth(Integer.MAX_VALUE);  //SearchView展开时设置最大宽度
                 //可以调整为其他合适宽度值
                    return true;
               }
    
                @Override
                 public boolean onMenuItemActionCollapse(MenuItem item) {
                    return true;
              }
            });
         }
    
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            // 搜索监听器代码
           //...
         });
    }
    

上述代码中, setOnActionExpandListener监听了SearchView的展开动作,当SearchView展开时,我们将其宽度设置为 Integer.MAX_VALUE (根据实际情况调整)。 收起时SearchView恢复到原始尺寸。

方案四: 使用 ActionViewClass

直接将 SearchView 作为 ActionViewClass 设置到 MenuItem 中,并在布局文件中单独定义 SearchView 的布局。 这种方式可以更灵活地控制 SearchView 的外观和行为。

  • 原理: 将SearchView定义为一个独立的布局文件,并通过设置actionViewClass属性将其添加到Toolbar。

  • 操作步骤:

    1. 创建一个 SearchView 布局文件 (例如: search_view_layout.xml):

      <?xml version="1.0" encoding="utf-8"?>
      <SearchView
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/search_view"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:maxWidth="300dp"    <!-- 根据实际情况设置 -->
          android:queryHint="搜索">
      </SearchView>
      
    2. 在 menu 文件 (menu_main.xml)中, 将 action_searchactionViewClass 属性设置为自定义的布局:

      <item
          android:id="@+id/action_search"
          android:title="搜索"
          android:icon="@drawable/ic_search_white_24dp"
          app:showAsAction="ifRoom|collapseActionView"
          app:actionViewClass="android.widget.SearchView"
          />
      
    3. 在 Fragment 的 onCreateOptionsMenu 方法中, 找到 SearchView 并进行相关配置。

  • 代码示例

    ```java
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         getBaseActivity().getMenuInflater().inflate(R.menu.menu_main, menu);
    
         MenuItem searchMenuItem = menu.findItem(R.id.action_search);
    
         // 将SearchView设置为ActionView
         SearchView searchView = (SearchView) searchMenuItem.getActionView();
    
        SearchManager searchManager = (SearchManager) getBaseActivity().getSystemService(Context.SEARCH_SERVICE);
         if(searchManager !=null){
           searchView.setSearchableInfo(searchManager.getSearchableInfo(getBaseActivity().getComponentName()));
         }
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
           // ...搜索监听代码
         });
      }
    
    ```
    

本方案将 SearchView 提取到单独的布局文件中,使其与 Toolbar 的布局解耦,方便自定义 SearchView 的外观和行为。 同时,在 menu_main.xml 文件中, 使用 actionViewClass 属性将 SearchView 与 MenuItem 关联。在 onCreateOptionsMenu() 方法中进行SearchView的配置。

以上几种方案可以根据具体情况选择使用,或者组合使用。 通过合理的布局和代码调整,可以解决 SearchView 导致的 Toolbar 尺寸变化问题,并实现流畅的搜索体验。

安全建议

  • 输入校验 : 确保对用户输入的搜索关键词进行校验,防止注入攻击或其他安全问题。
  • 数据过滤 : 对搜索结果进行过滤,避免显示敏感信息。

相关资源