Создание SearchView, которое выглядит как руководство по дизайну материала

134

В настоящее время я нахожусь в процессе изучения того, как преобразовать мое приложение в дизайн материалов, и сейчас я немного застрял. Мне добавили панель инструментов, и я переместил свой навигационный ящик на весь контент.

Сейчас я пытаюсь создать расширяемый поиск, похожий на тот, который приведен в руководстве по материалам : введите описание изображения здесь

это то, что у меня есть сейчас, и я не могу понять, как сделать это, как указано выше:
Мой поиск

Это мое меню 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:icon="@android:drawable/ic_menu_search"
        android:title="Search"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

Это работает, я получаю пункт меню, который расширяется до SearchView, и я могу отфильтровать свой список в порядке. Это не похоже на первую картинку.

Я пытался использовать MenuItemCompat.setOnActionExpandListener()на R.id.action_searchтак что я мог бы изменить значок домой к задней стрелки, но это не похоже на работу. Ничто не срабатывает в слушателе. Даже если бы это сработало, оно все равно не было бы очень близко к 1-му изображению.

Как создать SearchView на новой панели инструментов appcompat, которая выглядит как руководство по материалам?

Майк
источник
6
app: showAsAction = "always | collapseActionView"
Pavlos
Возможно, вы захотите взглянуть на мой ответ здесь: stackoverflow.com/a/41013994/5326551
shnizlon

Ответы:

152

На самом деле это довольно легко сделать, если вы используете android.support.v7библиотеку.

Шаг 1

Объявить пункт меню

<item android:id="@+id/action_search"
    android:title="Search"
    android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
    app:showAsAction="ifRoom|collapseActionView"
    app:actionViewClass="android.support.v7.widget.SearchView" />

Шаг 2

Расширьте AppCompatActivityи в onCreateOptionsMenuнастройках SearchView.

import android.support.v7.widget.SearchView;

...

public class YourActivity extends AppCompatActivity {

    ...

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_home, menu);
        // Retrieve the SearchView and plug it into SearchManager
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));
        SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        return true;
    }

    ... 

}

результат

введите описание изображения здесь

введите описание изображения здесь

Субин Себастьян
источник
2
Я проголосовал против, но какой эмулятор вы используете? Я пробовал, но у меня не navigate-backкнопка, а значок поиска, и его расстояние от левого края экрана не такое, как между Xзначком и правым краем экрана (у меня нет переполнение действий). Выложил вопрос здесь , можете посмотреть?
Утешение
13
это не материальный поиск. это только обычный старый поиск в панели действий
Гопал Сингх Сирви
2
Я ответил на свой собственный подвопрос, чтобы он всегда был виден без необходимости нажимать на кнопку поиска, добавить строку searchView.setIconifiedByDefault(false);в onCreateOptionsMenuфункцию.
adelriosantiago
3
Еще один полезный трюк - если вы хотите, чтобы представление поиска было расширено, сначала убедитесь, что вы это сделали, app:showAsAction="always"а НЕapp:showAsAction="ifRoom|collapseActionView"
Vinay W
1
Кроме того, используя этот метод, даже когда searchBar развернут, OverflowIcon все еще виден (то есть, 3 точки). Но некоторые приложения обрабатывают поиск, полностью расширяя его и меняя фон на белый. Нравится GMail
Zen
83

После недели недоумения по этому поводу. Я думаю, что я понял это.
Сейчас я использую только EditText внутри панели инструментов. Это было предложено мне oj88 на Reddit.

Теперь у меня есть это:
Новый SearchView

сначала внутри onCreate () моей деятельности я добавил EditText с видом изображения с правой стороны на панель инструментов следующим образом:

    // Setup search container view
    searchContainer = new LinearLayout(this);
    Toolbar.LayoutParams containerParams = new Toolbar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    containerParams.gravity = Gravity.CENTER_VERTICAL;
    searchContainer.setLayoutParams(containerParams);

    // Setup search view
    toolbarSearchView = new EditText(this);
    // Set width / height / gravity
    int[] textSizeAttr = new int[]{android.R.attr.actionBarSize};
    int indexOfAttrTextSize = 0;
    TypedArray a = obtainStyledAttributes(new TypedValue().data, textSizeAttr);
    int actionBarHeight = a.getDimensionPixelSize(indexOfAttrTextSize, -1);
    a.recycle();
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, actionBarHeight);
    params.gravity = Gravity.CENTER_VERTICAL;
    params.weight = 1;
    toolbarSearchView.setLayoutParams(params);

    // Setup display
    toolbarSearchView.setBackgroundColor(Color.TRANSPARENT);
    toolbarSearchView.setPadding(2, 0, 0, 0);
    toolbarSearchView.setTextColor(Color.WHITE);
    toolbarSearchView.setGravity(Gravity.CENTER_VERTICAL);
    toolbarSearchView.setSingleLine(true);
    toolbarSearchView.setImeActionLabel("Search", EditorInfo.IME_ACTION_UNSPECIFIED);
    toolbarSearchView.setHint("Search");
    toolbarSearchView.setHintTextColor(Color.parseColor("#b3ffffff"));
    try {
        // Set cursor colour to white
        // https://stackoverflow.com/a/26544231/1692770
        // https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564
        Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
        f.setAccessible(true);
        f.set(toolbarSearchView, R.drawable.edittext_whitecursor);
    } catch (Exception ignored) {
    }

    // Search text changed listener
    toolbarSearchView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            Fragment mainFragment = getFragmentManager().findFragmentById(R.id.container);
            if (mainFragment != null && mainFragment instanceof MainListFragment) {
                ((MainListFragment) mainFragment).search(s.toString());
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
            // https://stackoverflow.com/a/6438918/1692770
            if (s.toString().length() <= 0) {
                toolbarSearchView.setHintTextColor(Color.parseColor("#b3ffffff"));
            }
        }
    });
    ((LinearLayout) searchContainer).addView(toolbarSearchView);

    // Setup the clear button
    searchClearButton = new ImageView(this);
    Resources r = getResources();
    int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, r.getDisplayMetrics());
    LinearLayout.LayoutParams clearParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    clearParams.gravity = Gravity.CENTER;
    searchClearButton.setLayoutParams(clearParams);
    searchClearButton.setImageResource(R.drawable.ic_close_white_24dp); // TODO: Get this image from here: https://github.com/google/material-design-icons
    searchClearButton.setPadding(px, 0, px, 0);
    searchClearButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            toolbarSearchView.setText("");
        }
    });
    ((LinearLayout) searchContainer).addView(searchClearButton);

    // Add search view to toolbar and hide it
    searchContainer.setVisibility(View.GONE);
    toolbar.addView(searchContainer);

Это сработало, но затем я столкнулся с проблемой, когда onOptionsItemSelected () не вызывался, когда я нажимал на кнопку домой. Поэтому я не смог отменить поиск, нажав кнопку домой. Я пробовал несколько разных способов регистрации прослушивателя щелчка на кнопке «Домой», но они не работали.

В конце концов я обнаружил, что ActionBarDrawerToggle, который у меня был, мешал вещам, поэтому я удалил его. Затем этот слушатель начал работать:

    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // toolbarHomeButtonAnimating is a boolean that is initialized as false. It's used to stop the user pressing the home button while it is animating and breaking things.
            if (!toolbarHomeButtonAnimating) {
                // Here you'll want to check if you have a search query set, if you don't then hide the search box.
                // My main fragment handles this stuff, so I call its methods.
                FragmentManager fragmentManager = getFragmentManager();
                final Fragment fragment = fragmentManager.findFragmentById(R.id.container);
                if (fragment != null && fragment instanceof MainListFragment) {
                    if (((MainListFragment) fragment).hasSearchQuery() || searchContainer.getVisibility() == View.VISIBLE) {
                        displaySearchView(false);
                        return;
                    }
                }
            }

            if (mDrawerLayout.isDrawerOpen(findViewById(R.id.navigation_drawer)))
                mDrawerLayout.closeDrawer(findViewById(R.id.navigation_drawer));
            else
                mDrawerLayout.openDrawer(findViewById(R.id.navigation_drawer));
        }
    });

Теперь я могу отменить поиск с помощью кнопки «Домой», но пока не могу нажать кнопку «Назад», чтобы отменить поиск. Поэтому я добавил это в onBackPressed ():

    FragmentManager fragmentManager = getFragmentManager();
    final Fragment mainFragment = fragmentManager.findFragmentById(R.id.container);
    if (mainFragment != null && mainFragment instanceof MainListFragment) {
        if (((MainListFragment) mainFragment).hasSearchQuery() || searchContainer.getVisibility() == View.VISIBLE) {
            displaySearchView(false);
            return;
        }
    }

Я создал этот метод для переключения видимости EditText и пункта меню:

public void displaySearchView(boolean visible) {
    if (visible) {
        // Stops user from being able to open drawer while searching
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);

        // Hide search button, display EditText
        menu.findItem(R.id.action_search).setVisible(false);
        searchContainer.setVisibility(View.VISIBLE);

        // Animate the home icon to the back arrow
        toggleActionBarIcon(ActionDrawableState.ARROW, mDrawerToggle, true);

        // Shift focus to the search EditText
        toolbarSearchView.requestFocus();

        // Pop up the soft keyboard
        new Handler().postDelayed(new Runnable() {
            public void run() {
                toolbarSearchView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 0, 0, 0));
                toolbarSearchView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 0, 0, 0));
            }
        }, 200);
    } else {
        // Allows user to open drawer again
        mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);

        // Hide the EditText and put the search button back on the Toolbar.
        // This sometimes fails when it isn't postDelayed(), don't know why.
        toolbarSearchView.postDelayed(new Runnable() {
            @Override
            public void run() {
                toolbarSearchView.setText("");
                searchContainer.setVisibility(View.GONE);
                menu.findItem(R.id.action_search).setVisible(true);
            }
        }, 200);

        // Turn the home button back into a drawer icon
        toggleActionBarIcon(ActionDrawableState.BURGER, mDrawerToggle, true);

        // Hide the keyboard because the search box has been hidden
        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(toolbarSearchView.getWindowToken(), 0);
    }
}

Мне нужен был способ переключения кнопки «Домой» на панели инструментов между значком ящика и кнопкой «Назад». В конце концов я нашел метод ниже в этом ответе . Хотя я немного изменил его, чтобы придать мне больше смысла:

private enum ActionDrawableState {
    BURGER, ARROW
}

/**
 * Modified version of this, https://stackoverflow.com/a/26836272/1692770<br>
 * I flipped the start offset around for the animations because it seemed like it was the wrong way around to me.<br>
 * I also added a listener to the animation so I can find out when the home button has finished rotating.
 */
private void toggleActionBarIcon(final ActionDrawableState state, final ActionBarDrawerToggle toggle, boolean animate) {
    if (animate) {
        float start = state == ActionDrawableState.BURGER ? 1.0f : 0f;
        float end = Math.abs(start - 1);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
            offsetAnimator.setDuration(300);
            offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
            offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float offset = (Float) animation.getAnimatedValue();
                    toggle.onDrawerSlide(null, offset);
                }
            });
            offsetAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    toolbarHomeButtonAnimating = false;
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            toolbarHomeButtonAnimating = true;
            offsetAnimator.start();
        }
    } else {
        if (state == ActionDrawableState.BURGER) {
            toggle.onDrawerClosed(null);
        } else {
            toggle.onDrawerOpened(null);
        }
    }
}

Это работает, мне удалось выявить несколько ошибок, которые я обнаружил по пути. Я не думаю, что это 100%, но это работает достаточно хорошо для меня.

РЕДАКТИРОВАТЬ: Если вы хотите добавить представление поиска в XML вместо Java, сделайте следующее:

toolbar.xml:

<android.support.v7.widget.Toolbar 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    contentInsetLeft="72dp"
    contentInsetStart="72dp"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    android:minHeight="?attr/actionBarSize"
    app:contentInsetLeft="72dp"
    app:contentInsetStart="72dp"
    app:popupTheme="@style/ActionBarPopupThemeOverlay"
    app:theme="@style/ActionBarThemeOverlay">

    <LinearLayout
        android:id="@+id/search_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <EditText
            android:id="@+id/search_view"
            android:layout_width="0dp"
            android:layout_height="?attr/actionBarSize"
            android:layout_weight="1"
            android:background="@android:color/transparent"
            android:gravity="center_vertical"
            android:hint="Search"
            android:imeOptions="actionSearch"
            android:inputType="text"
            android:maxLines="1"
            android:paddingLeft="2dp"
            android:singleLine="true"
            android:textColor="#ffffff"
            android:textColorHint="#b3ffffff" />

        <ImageView
            android:id="@+id/search_clear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:src="@drawable/ic_close_white_24dp" />
    </LinearLayout>
</android.support.v7.widget.Toolbar>

onCreate () вашей активности:

    searchContainer = findViewById(R.id.search_container);
    toolbarSearchView = (EditText) findViewById(R.id.search_view);
    searchClearButton = (ImageView) findViewById(R.id.search_clear);

    // Setup search container view
    try {
        // Set cursor colour to white
        // https://stackoverflow.com/a/26544231/1692770
        // https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564
        Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
        f.setAccessible(true);
        f.set(toolbarSearchView, R.drawable.edittext_whitecursor);
    } catch (Exception ignored) {
    }

    // Search text changed listener
    toolbarSearchView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            Fragment mainFragment = getFragmentManager().findFragmentById(R.id.container);
            if (mainFragment != null && mainFragment instanceof MainListFragment) {
                ((MainListFragment) mainFragment).search(s.toString());
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });

    // Clear search text when clear button is tapped
    searchClearButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            toolbarSearchView.setText("");
        }
    });

    // Hide the search view
    searchContainer.setVisibility(View.GONE);
Майк
источник
Отлично работает, отлично выглядит, спасибо! Однако вместо создания макетов в коде я создал LinearLayout с EditText и ImageView в xml и просто накачал его в onCreate.
aluxian
Да, я пытался сделать это в XML, но мне показалось, что я делаю что-то не так, поскольку Android Studio не дает мне автозаполнения в XML-макете.
Майк
Не могли бы вы обновить этот ответ соответствующим дизайном XML-макета, необходимым для этого? это может помочь другим очень хорошо.
Шреяш Махаджан
1
@Mike Можете ли вы обновить свой ответ и поставить свой полный исходный код GitHub?
Хамед Гадириан
1
пожалуйста,
опубликуйте
22

Я знаю, что это старая ветка, но я все еще публикую библиотеку, которую только что создал. Надеюсь, это может кому-то помочь.

https://github.com/Shahroz16/material-searchview

Вид поиска по материалам

ShahrozKhan91
источник
1
Это не сложно, но мне нравится твоя работа. Это экономит мое время, чтобы создать свой собственный вид поиска. Спасибо брат!
Slim_user71169
19

Первый скриншот в вашем вопросе не является публичным виджетом. Поддержка SearchView ( android.support.v7.widget.SearchView) имитирует Android 5.0 Lollipop's SearchView ( android.widget.SearchView). Ваш второй снимок экрана используется другими приложениями, созданными с использованием материалов, такими как Google Play.

SearchView на вашем первом снимке экрана используется в Drive, YouTube и других закрытых приложениях Google Apps. К счастью, он также используется в Android 5.0 Dialer . Вы можете попытаться сделать бэкпорт для представления, но он использует некоторые API 5.0.

Классы, которые вы захотите посмотреть:

SearchEditTextLayout , AnimUtils и DialtactsActivity, чтобы понять, как использовать представление. Вам также понадобятся ресурсы из ContactsCommon .

Удачи.

Джаред Раммлер
источник
Спасибо за внимание, я надеялся, что уже есть что-то, что может это сделать. На данный момент я только что использовал EditText с прозрачным фоном, и мне кажется, что все в порядке.
Майк
111
Этот ответ очень беспокоит меня. Почему Google использует закрытый виджет, который соответствует своему собственному руководству по дизайну материалов, а затем публикует дрянной виджет для нас, который этого не делает? И каждый разработчик сейчас борется с этим самостоятельно? Каковы возможные причины этого?
Грег Эннис
18

Вот моя попытка сделать это:

Шаг 1. Создайте стиль с именем SearchViewStyle

<style name="SearchViewStyle" parent="Widget.AppCompat.SearchView">
    <!-- Gets rid of the search icon -->
    <item name="searchIcon">@drawable/search</item>
    <!-- Gets rid of the "underline" in the text -->
    <item name="queryBackground">@null</item>
    <!-- Gets rid of the search icon when the SearchView is expanded -->
    <item name="searchHintIcon">@null</item>
    <!-- The hint text that appears when the user has not typed anything -->
    <item name="queryHint">@string/search_hint</item>
</style>

Шаг 2. Создайте макет с именем simple_search_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.SearchView
    android:layout_gravity="end"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    style="@style/SearchViewStyle"
    xmlns:android="http://schemas.android.com/apk/res/android" />  

Шаг 3. Создайте пункт меню для этого вида поиска

<?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
        app:actionLayout="@layout/simple_search_view_item"
        android:title="@string/search"
        android:icon="@drawable/search"
        app:showAsAction="always" />
</menu>  

Шаг 4: надуть меню

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_searchable_activity, menu);
    return true;
}  

Результат:

введите описание изображения здесь

Единственное, что я не смог сделать, это заставить его заполнить всю ширину Toolbar. Если бы кто-то мог помочь мне сделать это, это было бы прекрасно.

ТАК пользователь
источник
1
I wasn't able to do was to make it fill the entire widthкакую версию библиотеки поддержки вы используете? Попробуйте установить app:contentInsetStartWithNavigation="0dp"для своей панели инструментов.
Мангеш
@LittleChild, попробуйте решение, данное Магнеш. Если проблема не решена, попробуйте добавить строки на панели инструментов ниже. app: contentInsetStartWithNavigation = "0dp" app: contentInsetLeft = "0dp" app: contentInsetStart = "0dp" app: paddingStart = "0dp" android: layout_marginLeft = "0dp" android: layout_marginStart = "0dp"
махаджан
Спасибо за то, что вы добавили объяснение для каждой строки в SearchViewStyle!
Shinta S
Маленький ребенок Для всей ширины вы можете сделать что-то вроде этого: (" stackoverflow.com/questions/27946569/… )
Ali_dev
10

Чтобы добиться желаемого вида SearchView, вы можете использовать стили.

Во-первых, вам нужно создать styleдля своего SearchView, который должен выглядеть примерно так:

<style name="CustomSearchView" parent="Widget.AppCompat.SearchView">
    <item name="searchIcon">@null</item>
    <item name="queryBackground">@null</item>
</style>

Весь список атрибутов вы можете найти в этой статье, в разделе «SearchView».

Во-вторых, вам нужно создать styleдля себя Toolbar, который используется как ActionBar:

<style name="ToolbarSearchView" parent="Base.ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="searchViewStyle">@style/CustomSearchView</item>
</style>

И, наконец, вам нужно обновить атрибут темы панели инструментов следующим образом:

<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:theme="@style/ToolbarSearchView" />

Результат:

введите описание изображения здесь

ПРИМЕЧАНИЕ. Вам необходимо Toolbarнапрямую изменить атрибут темы. Если вы просто обновите свой основной searchViewStyleатрибут темы, это не повлияет на ваш Toolbar.

Артем
источник
Эй, вы сами добавили эти значки navigate-back(стрелка назад) и cancel(x) или они были добавлены автоматически?
Утешение
1
@ Осталось, что они добавляются автоматически
Артем
Они появляются только тогда, когда вы начинаете писать поисковый запрос в SearchView, или они есть, даже если вы ничего не написали и подсказка поиска видна? Я спрашиваю, потому что мои не появляются, пока я не начну писать запрос. Так что эта информация будет очень полезна для меня
Утешение
1
@Утешение navigate-back всегда отображается, clearотображается только после того, как вы написали какой-то поисковый запрос.
Артем
6

Другой способ добиться желаемого эффекта - использовать эту библиотеку просмотра материалов . Он автоматически обрабатывает историю поиска и предоставляет возможность поиска для просмотра.

Пример: (он показан на португальском, но также работает на английском и итальянском языках).

Образец

Настроить

Прежде чем вы сможете использовать эту библиотеку, вы должны реализовать класс с именем MsvAuthority внутри br.com.maukerпакета, в вашем модуле приложения, и он должен иметь открытую статическую переменную String с именем CONTENT_AUTHORITY. Дайте ему желаемое значение и не забудьте добавить то же имя в файл манифеста. Библиотека будет использовать этот файл для установки полномочий контент-провайдера.

Пример:

MsvAuthority.java

package br.com.mauker;

public class MsvAuthority {
    public static final String CONTENT_AUTHORITY = "br.com.mauker.materialsearchview.searchhistorydatabase";
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>

    <application ... >
        <provider
        android:name="br.com.mauker.materialsearchview.db.HistoryProvider"
        android:authorities="br.com.mauker.materialsearchview.searchhistorydatabase"
        android:exported="false"
        android:protectionLevel="signature"
        android:syncable="true"/>
    </application>

</manifest>

использование

Чтобы использовать его, добавьте зависимость:

compile 'br.com.mauker.materialsearchview:materialsearchview:1.2.0'

А потом, по вашему Activity файл макета добавьте следующее:

<br.com.mauker.materialsearchview.MaterialSearchView
    android:id="@+id/search_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

После этого вам просто нужно получить MaterialSearchViewссылку с помощьюgetViewById() и открыть или закрыть ее с помощьюMaterialSearchView#openSearch() и MaterialSearchView#closeSearch().

PS: можно открывать и закрывать вид не только из Toolbar. Вы можете использовать openSearch()метод в основном из любогоButton , такого как кнопка с плавающим действием.

// Inside onCreate()
MaterialSearchView searchView = (MaterialSearchView) findViewById(R.id.search_view);
Button bt = (Button) findViewById(R.id.button);

bt.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            searchView.openSearch();
        }
    });

Вы также можете закрыть вид с помощью кнопки назад, выполнив следующие действия:

@Override
public void onBackPressed() {
    if (searchView.isOpen()) {
        // Close the search on the back button press.
        searchView.closeSearch();
    } else {
        super.onBackPressed();
    }
}

Для получения дополнительной информации о том, как использовать lib, проверьте страницу github .

Mauker
источник
2
Отличная библиотека и отличная идея абстрагировать метод открытия / закрытия, чтобы MenuItem не требовал его открытия / закрытия, я планирую использовать это в своем приложении с FloatingActionButton со значком поиска, поэтому он будет отлично работать.
AdamMc331
Почему нет параметров для строк, таких как «Поиск»? Кажется, библиотека ограничивает людей английской или португальской версиями строки: /
Aspiring Dev
Но можно изменить строку подсказки, используя стили, как указано в README. Что касается подсказки голосового ввода, она будет выпущена позже: github.com/Mauker1/MaterialSearchView/issues/23
Mauker
@rpgmaker Проверьте последнее обновление, теперь можно изменить эти строки.
Маукер
@Mauker есть идеи, как установить Android: imeOptions = "actionSearch" для EditText вашего компонента? (Я хочу отобразить кнопку «поиск» на клавиатуре)
Грег
2

Следующее создаст SearchView, идентичный тому, что в Gmail, и добавит его на заданную панель инструментов. Вам просто нужно реализовать свой собственный метод «ViewUtil.convertDpToPixel».

private SearchView createMaterialSearchView(Toolbar toolbar, String hintText) {

    setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setDisplayShowCustomEnabled(true);
    actionBar.setDisplayShowTitleEnabled(false);

    SearchView searchView = new SearchView(this);
    searchView.setIconifiedByDefault(false);
    searchView.setMaxWidth(Integer.MAX_VALUE);
    searchView.setMinimumHeight(Integer.MAX_VALUE);
    searchView.setQueryHint(hintText);

    int rightMarginFrame = 0;
    View frame = searchView.findViewById(getResources().getIdentifier("android:id/search_edit_frame", null, null));
    if (frame != null) {
        LinearLayout.LayoutParams frameParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        rightMarginFrame = ((LinearLayout.LayoutParams) frame.getLayoutParams()).rightMargin;
        frameParams.setMargins(0, 0, 0, 0);
        frame.setLayoutParams(frameParams);
    }

    View plate = searchView.findViewById(getResources().getIdentifier("android:id/search_plate", null, null));
    if (plate != null) {
        plate.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        plate.setPadding(0, 0, rightMarginFrame, 0);
        plate.setBackgroundColor(Color.TRANSPARENT);
    }

    int autoCompleteId = getResources().getIdentifier("android:id/search_src_text", null, null);
    if (searchView.findViewById(autoCompleteId) != null) {
        EditText autoComplete = (EditText) searchView.findViewById(autoCompleteId);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int) ViewUtil.convertDpToPixel(36));
        params.weight = 1;
        params.gravity = Gravity.CENTER_VERTICAL;
        params.leftMargin = rightMarginFrame;
        autoComplete.setLayoutParams(params);
        autoComplete.setTextSize(16f);
    }

    int searchMagId = getResources().getIdentifier("android:id/search_mag_icon", null, null);
    if (searchView.findViewById(searchMagId) != null) {
        ImageView v = (ImageView) searchView.findViewById(searchMagId);
        v.setImageDrawable(null);
        v.setPadding(0, 0, 0, 0);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        params.setMargins(0, 0, 0, 0);
        v.setLayoutParams(params);
    }

    toolbar.setTitle(null);
    toolbar.setContentInsetsAbsolute(0, 0);
    toolbar.addView(searchView);

    return searchView;
}

источник