android 工具栏中 SearchView 的正确实现
Correct implementation of SearchView in android toolbar
我在 android 工具栏中执行搜索视图时遇到问题。
- 空 space 填充太大。
- 我不想隐藏其他动作,但这些动作是
与 SearchView 重叠。
- SearchView 的下划线不可见
我该如何解决上述问题?
menu.xml
<?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/action_search"
android:title="@string/car_num"
android:icon="@drawable/ic_search_white_24dp"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
<item
android:id="@+id/action_add_client"
android:icon="@drawable/ic_account_multiple_plus"
android:title="@string/action_add_client"
app:showAsAction="always" />
</menu>
片段
@Override
public void onCreateOptionsMenu(final Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment_reg_vehicles, menu);
final MenuItem item = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setQueryHint("Search");
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(this);
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
setItemsVisibility(menu, item, true);
return false;
}
});
searchView.setOnSearchClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setItemsVisibility(menu, item, false);
searchView.requestFocus();
}
});
}
关于您发布的代码,这是输出:
如您所见,有两个左边距:小部件的容器和放大图标。这就是为什么你有一个空的 space 比另一个有标题的 window 大。并且菜单项被推到工具栏之外,我认为它是默认的 SearchView ActionView
而不是 CollapseActionView
所以它填充 parent.
从 SearchView
小部件的来源及其布局 abc_search_view.xml,我试图删除额外的边距并避免将其他项目推到工具栏之外。
但经过多次操作,我猜你必须使用自定义小部件 and/or 自定义布局。或者使用 setIconifiedByDefault(true)
删除放大图标及其额外边距并使用 setMaxWidth(MAX_SIZE)
其中 MAX_SIZE
由 Integer.MAX_VALUE - (SIZE_OF_A_MENU_ITEM * NB_OF_MENU_ITEMS)
动态计算......但它需要很多白干活。因此,使用自定义布局可能是解决方案。
但是,有一种可能的方法来保留应用程序兼容性小部件,一些小的解决方法。首先,为避免推出其他项目,您可以使用 CollapseActionView
。
<item
...
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
并且为了保持您的要求,您必须在初始化时扩展它:
final SearchView searchView =
(SearchView) MenuItemCompat.getActionView(item);
MenuItemCompat.expandActionView(item);
请注意,如果您不想折叠该项目,则必须使用 setOnActionExpandListener()
才能关闭 window。 此建议会给你这个结果:
还有额外的边距,对吧?因此,您必须通过它们的 ID 检索容器和放大图标(您可以在 abc_search_view.xml
... 中找到它们,但让我们节省一些时间:它们是 R.id.search_edit_frame
和 R.id.search_mag_icon
)。您可以使用此方法删除它们的边距:
private void changeSearchViewElements(View view) {
if (view == null)
return;
if (view.getId() == R.id.search_edit_frame
|| view.getId() == R.id.search_mag_icon) {
LinearLayout.LayoutParams p =
(LinearLayout.LayoutParams) view.getLayoutParams();
p.leftMargin = 0; // set no left margin
view.setLayoutParams(p);
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
changeSearchViewElements(viewGroup.getChildAt(i));
}
}
}
通过在线程中调用它:
final SearchView searchView =
(SearchView) MenuItemCompat.getActionView(item);
...
searchView.post(new Runnable() {
@Override
public void run() {
changeSearchViewElements(searchView);
}
});
这是输出:
最后,要在字段下方添加线条,有一个可能的解决方法,即使用 9 补丁可绘制对象并将其设置为背景。您可以在 Google 上轻松找到 how-to。所以条件将是:
private void changeSearchViewElements(View view) {
...
if (view.getId() == R.id.search_edit_frame
|| view.getId() == R.id.search_mag_icon) {
LinearLayout.LayoutParams p =
(LinearLayout.LayoutParams) view.getLayoutParams();
p.leftMargin = 0; // set no left margin
view.setLayoutParams(p);
} else if (view.getId() == R.id.search_src_text) {
AutoCompleteTextView searchEdit = (AutoCompleteTextView) view;
searchEdit.setBackgroundResource(R.drawable.rect_underline_white);
}
...
}
从OP下面的评论来看,下划线的字段也可以用下面的语句来完成:
searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text)
.setBackgroundResource(R.drawable.abc_textfield_search_default_mtrl_alpha);
如我所说,在这些解决方法之后,使用自定义布局可能会更容易。但如果您想保留默认的 SearchView 小部件,这可能会有所帮助。
我在 android 工具栏中执行搜索视图时遇到问题。
- 空 space 填充太大。
- 我不想隐藏其他动作,但这些动作是 与 SearchView 重叠。
- SearchView 的下划线不可见
我该如何解决上述问题?
menu.xml
<?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/action_search"
android:title="@string/car_num"
android:icon="@drawable/ic_search_white_24dp"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
<item
android:id="@+id/action_add_client"
android:icon="@drawable/ic_account_multiple_plus"
android:title="@string/action_add_client"
app:showAsAction="always" />
</menu>
片段
@Override
public void onCreateOptionsMenu(final Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_fragment_reg_vehicles, menu);
final MenuItem item = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(item);
searchView.setQueryHint("Search");
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(this);
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
setItemsVisibility(menu, item, true);
return false;
}
});
searchView.setOnSearchClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setItemsVisibility(menu, item, false);
searchView.requestFocus();
}
});
}
关于您发布的代码,这是输出:
如您所见,有两个左边距:小部件的容器和放大图标。这就是为什么你有一个空的 space 比另一个有标题的 window 大。并且菜单项被推到工具栏之外,我认为它是默认的 SearchView ActionView
而不是 CollapseActionView
所以它填充 parent.
从 SearchView
小部件的来源及其布局 abc_search_view.xml,我试图删除额外的边距并避免将其他项目推到工具栏之外。
但经过多次操作,我猜你必须使用自定义小部件 and/or 自定义布局。或者使用 setIconifiedByDefault(true)
删除放大图标及其额外边距并使用 setMaxWidth(MAX_SIZE)
其中 MAX_SIZE
由 Integer.MAX_VALUE - (SIZE_OF_A_MENU_ITEM * NB_OF_MENU_ITEMS)
动态计算......但它需要很多白干活。因此,使用自定义布局可能是解决方案。
但是,有一种可能的方法来保留应用程序兼容性小部件,一些小的解决方法。首先,为避免推出其他项目,您可以使用 CollapseActionView
。
<item
...
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always|collapseActionView"/>
并且为了保持您的要求,您必须在初始化时扩展它:
final SearchView searchView =
(SearchView) MenuItemCompat.getActionView(item);
MenuItemCompat.expandActionView(item);
请注意,如果您不想折叠该项目,则必须使用 setOnActionExpandListener()
才能关闭 window。 此建议会给你这个结果:
还有额外的边距,对吧?因此,您必须通过它们的 ID 检索容器和放大图标(您可以在 abc_search_view.xml
... 中找到它们,但让我们节省一些时间:它们是 R.id.search_edit_frame
和 R.id.search_mag_icon
)。您可以使用此方法删除它们的边距:
private void changeSearchViewElements(View view) {
if (view == null)
return;
if (view.getId() == R.id.search_edit_frame
|| view.getId() == R.id.search_mag_icon) {
LinearLayout.LayoutParams p =
(LinearLayout.LayoutParams) view.getLayoutParams();
p.leftMargin = 0; // set no left margin
view.setLayoutParams(p);
}
if (view instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
changeSearchViewElements(viewGroup.getChildAt(i));
}
}
}
通过在线程中调用它:
final SearchView searchView =
(SearchView) MenuItemCompat.getActionView(item);
...
searchView.post(new Runnable() {
@Override
public void run() {
changeSearchViewElements(searchView);
}
});
这是输出:
最后,要在字段下方添加线条,有一个可能的解决方法,即使用 9 补丁可绘制对象并将其设置为背景。您可以在 Google 上轻松找到 how-to。所以条件将是:
private void changeSearchViewElements(View view) {
...
if (view.getId() == R.id.search_edit_frame
|| view.getId() == R.id.search_mag_icon) {
LinearLayout.LayoutParams p =
(LinearLayout.LayoutParams) view.getLayoutParams();
p.leftMargin = 0; // set no left margin
view.setLayoutParams(p);
} else if (view.getId() == R.id.search_src_text) {
AutoCompleteTextView searchEdit = (AutoCompleteTextView) view;
searchEdit.setBackgroundResource(R.drawable.rect_underline_white);
}
...
}
从OP下面的评论来看,下划线的字段也可以用下面的语句来完成:
searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text)
.setBackgroundResource(R.drawable.abc_textfield_search_default_mtrl_alpha);
如我所说,在这些解决方法之后,使用自定义布局可能会更容易。但如果您想保留默认的 SearchView 小部件,这可能会有所帮助。