安卓:动画搜索视图

4

我正在尝试实现一个带有简单展开/收缩动画效果的搜索视图,但是在这个论坛中的所有答案都无法正常工作。

<item
    android:id="@+id/action_search"
    android:orderInCategory="100"
    android:title="@string/action_search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    android:icon="@drawable/ic_search_white_48px"
    app:showAsAction="always"/>

我所做的

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
    //Get the ID for the search bar LinearLayout
    int searchBarId = searchView.getContext().getResources().getIdentifier("android:id/search_bar", null, null);
    //Get the search bar Linearlayout
    LinearLayout searchBar = (LinearLayout) 
            searchView.findViewById(searchBarId);
    //Give the Linearlayout a transition animation.
    searchBar.setLayoutTransition(new LayoutTransition());
    return true;
}

所有错误:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.daveslab.wideview, PID: 2459
              java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.LinearLayout.setLayoutTransition(android.animation.LayoutTransition)' on a null object reference
                  at com.daveslab.wideview.MainActivity.onCreateOptionsMenu(MainActivity.java:69)
                  at android.app.Activity.onCreatePanelMenu(Activity.java:2846)
                  at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:360)
                  at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:88)
                  at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.onCreatePanelMenu(AppCompatDelegateImplBase.java:331)
                  at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:88)
                  at android.support.v7.app.ToolbarActionBar.populateOptionsMenu(ToolbarActionBar.java:454)
                  at android.support.v7.app.ToolbarActionBar$1.run(ToolbarActionBar.java:61)
                  at android.os.Handler.handleCallback(Handler.java:739)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:148)
                  at android.app.ActivityThread.main(ActivityThread.java:5417)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

values.xml 中的错误(所有图标都已经以正确的名称在项目中):

Error:(1605, 21) No resource found that matches the given name: attr 'searchBackIcon'.

错误:(1602, 21)没有找到与给定名称匹配的资源:attr' searchBackground'。 错误:(1604, 21)没有找到与给定名称匹配的资源:attr' searchCloseIcon'。 错误:(1606, 21)没有找到与给定名称匹配的资源:attr' searchSuggestionBackground'。 错误:(1603, 21)没有找到与给定名称匹配的资源:attr' searchVoiceIcon'。 错误:(1605, 21)没有找到与给定名称匹配的资源:attr' searchBackIcon'。 错误:(1602, 21)没有找到与给定名称匹配的资源:attr' searchBackground'。 错误:(1604, 21)没有找到与给定名称匹配的资源:attr' searchCloseIcon'。 错误:(1606, 21)没有找到与给定名称匹配的资源:attr' searchSuggestionBackground'。 错误:(1603, 21)没有找到与给定名称匹配的资源:attr' searchVoiceIcon'。 错误:执行任务“:app:processDebugResources”失败。 com.android.ide.common.process.ProcessException:未能执行aapt。
3个回答

3

有一种更简单的方法(实际上只需要两行代码),而且它是没有错误的。您需要做的是在onCreateOptionsMenu()方法中填充SearchView,就像以前所做的那样,但避免设置过渡的代码行,因为它们不再需要。

接下来,像这样重写onOptionsItemSelected():

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    switch(item.getItemId()) {
        case R.id.action_search:
            TransitionManager.beginDelayedTransition((ViewGroup) getActivity().findViewById(R.id.toolbar));
            MenuItemCompat.expandActionView(item);
            return true;
    }
    return super.onOptionsItemSelected(item);
}

这段代码准备了一个转换,并监听工具栏布局的变化。当SearchView出现时,动画就开始了。它使用与KitKat相同的API,但从ICS开始可用。在您的build.gradle中:

compile 'com.android.support:transition:24.2.1'

你可以 自定义转换效果,如果你不喜欢默认的效果。

那是因为该代码是从一个片段中运行的。如果您正在从活动处理SearchView,则只需使用findViewById(...)即可。 - javmarina
我正在通过MainActivity.java运行它。 - Davide Nale
在这种情况下,您的代码行是TransitionManager.beginDelayedTransition((ViewGroup) findViewById(R.id.toolbar)); - javmarina
1
现在它可以工作了,但是它会在几秒钟内消失。有可能实现一个可见的过渡效果吗? - Davide Nale
您可以随时自定义转换,提供自己的设置。您看到的动画是默认的(系统选择的动画)。有一个方法TransitionManager.beginDelayedTransition(ViewGroup, Transition),您可以在其中提供自定义动画。更多信息请参见https://developer.android.com/reference/android/transition/TransitionManager.html和https://developer.android.com/training/transitions/overview.html。 - javmarina

1

我回答有点晚,但以上答案对我没有用。

     SearchView searchView;
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.application_menu, menu);
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        searchView = (SearchView) menu.findItem(R.id.app_bar_search).getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        LinearLayout searchBar = (LinearLayout) searchView.findViewById(R.id.search_bar);
        searchBar.setLayoutTransition(new LayoutTransition());
 return super.onCreateOptionsMenu(menu);
        }

我的application_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/app_bar_search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="Search"
        app:showAsAction="ifRoom"
         />

</menu>

0

这可能对你有所帮助。但如果它解决了你的问题,请接受答案。这样,它也会帮助其他人。

SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
//Get the ID for the search bar LinearLayout
int searchBarId = searchView.getContext().getResources().getIdentifier("android:id/search_bar", null, null);
//Get the search bar Linearlayout
 LinearLayout searchBar = (LinearLayout)       
 searchView.findViewById(searchBarId);
 //Give the Linearlayout a transition animation.
 searchBar.setLayoutTransition(new LayoutTransition());

Styles.xml

  <style name="MaterialSearchViewStyle">
    <item name="searchBackground">@color/white_ish</item>
    <item name="searchVoiceIcon">@drawable/ic_action_voice_search</item>
    <item name="searchCloseIcon">@drawable/ic_action_navigation_close</item>
    <item name="searchBackIcon">@drawable/ic_action_navigation_arrow_back</item>
    <item name="searchSuggestionBackground">@color/search_layover_bg</item>
    <item name="android:textColor">@color/black</item>
    <item name="android:textColorHint">@color/gray_50</item>
    <item name="android:hint">@string/search_hint</item>
    <item name="android:inputType">textCapWords</item>
</style>

在你的 XML 中使用那样的样式

<item
android:id="@+id/action_search"
android:orderInCategory="100"
android:title="@string/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
android:icon="@drawable/ic_search_white_48px"
app:showAsAction="always"
 style="@style/MaterialSearchViewStyle"/>

和控制台日志 - Davide Nale
@DavideNale 运行了这段代码之后,有错误提示信息吗?请分享错误截图。 - Asad Ali
好的。请在问题正文中查找。 - Davide Nale
@DavideNale 你必须定义样式。 - Asad Ali
@DavideNale 在回答中添加了 - Asad Ali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接