Implementieren von SearchView gemäß den Material Design Guidelines

Lesezeit: 22 Minuten

Benutzer-Avatar
GunnerFan

Ich habe nach Möglichkeiten gesucht, eine Suchansicht in der Aktivitätssymbolleiste (Actionbar) gemäß der zu implementieren Richtlinien für Materialdesign.

Wenn Sie auf das Suchsymbol klicken, wird die gesamte Symbolleiste so animiert, dass nur die Suche EditText mit weißem Hintergrund mit Vorschlägen in der Hauptansicht anstelle eines Dropdown-Menüs angezeigt wird.

Hier ist ein Screenshot aus den Richtlinien:
Geben Sie hier die Bildbeschreibung ein

Hier ist ein GIF aus der Gmail-Inbox-Implementierung:
Geben Sie hier die Bildbeschreibung ein

Ich habe nach Codebeispielen und Tutorials gesucht, aber bisher war ich erfolglos. Wie mache ich das?

  • ist das nicht ein Duplikat von stackoverflow.com/questions/27556623/… ?

    – Adam Burley

    26. Januar 2021 um 17:11 Uhr

Benutzer-Avatar
schnizlon

Ich habe mehrere SearchView-Materialbibliotheken ausprobiert, aber keine davon hat so gut funktioniert wie die aus der Support-Bibliothek, also habe ich mich entschieden, sie neu zu gestalten. Nach viel Arbeit bin ich mit dem Ergebnis zufrieden:

Geben Sie hier die Bildbeschreibung ein

So können Sie es tun:

1) Fügen Sie das SearchView-Element zu Ihrem Menü hinzu

<item
    android:id="@+id/m_search"
    android:icon="@drawable/ic_action_search"
    android:title="@string/search_title"
    app:actionLayout="@layout/search_view_layout"
    app:showAsAction="ifRoom|collapseActionView" />

Beachten Sie, dass ich erkläre AktionLayout Anstatt von actionViewClassdachte ich, dass dies die einzige Möglichkeit ist, das SearchView-Design separat vom Toolbar-Design festzulegen.

search_view_layout.xml:

<android.support.v7.widget.SearchView
    android:id="@+id/search_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/SearchViewTheme" />

2) Fügen Sie das benutzerdefinierte SearchView-Design zu Ihren Stilen hinzu, deklarieren Sie das SearchView-Design auch in Ihrem Toolbar-Design:

<style name="SearchViewTheme" parent="Widget.AppCompat.SearchView.ActionBar">
    <item name="layout">@layout/toolbar_search_view</item>
    <item name="commitIcon">@drawable/ic_search_commit</item>
    <item name="colorControlNormal">@color/material_light_active_icon</item>
    <item name="colorControlHighlight">@color/material_ripple_light</item>
    <item name="autoCompleteTextViewStyle">@style/AutoCompleteTextViewStyle</item>
    <item name="suggestionRowLayout">@layout/search_view_suggestion_row</item>
    <item name="android:maxWidth">9999dp</item>
</style>

<style name="AutoCompleteTextViewStyle" parent="Widget.AppCompat.Light.AutoCompleteTextView">
    <item name="android:popupBackground">@drawable/search_suggestions_bg</item>
    <item name="android:popupElevation">0dp</item>
</style>

<style name="ToolbarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="searchViewStyle">@style/SearchViewTheme</item>
</style>

toolbar_search_view.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/search_bar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:paddingEnd="8dp">

<!-- This is actually used for the badge icon *or* the badge label (or neither) -->
<TextView
    android:id="@+id/search_badge"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginBottom="2dp"
    android:drawablePadding="0dp"
    android:gravity="center_vertical"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:textColor="?android:attr/textColorPrimary"
    android:visibility="gone" />

<ImageView
    android:id="@+id/search_button"
    style="?attr/actionButtonStyle"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="center_vertical"
    android:contentDescription="@string/abc_searchview_description_search"
    android:focusable="true" />

<LinearLayout
    android:id="@+id/search_edit_frame"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:layoutDirection="locale"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/search_mag_icon"
        style="@style/RtlOverlay.Widget.AppCompat.SearchView.MagIcon"
        android:layout_width="@dimen/abc_dropdownitem_icon_width"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:scaleType="centerInside"
        android:visibility="gone" />

    <!-- Inner layout contains the app icon, button(s) and EditText -->
    <LinearLayout
        android:id="@+id/search_plate"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:orientation="horizontal">

        <view
            android:id="@+id/search_src_text"
            class="android.support.v7.widget.SearchView$SearchAutoComplete"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:layout_marginEnd="@dimen/item_list_horizontal_margin"
            android:layout_marginStart="@dimen/item_list_horizontal_margin"
            android:layout_weight="1"
            android:background="@null"
            android:dropDownAnchor="@id/anchor_dropdown"
            android:dropDownHeight="wrap_content"
            android:dropDownHorizontalOffset="0dp"
            android:dropDownVerticalOffset="0dp"
            android:ellipsize="end"
            android:imeOptions="actionSearch"
            android:inputType="text|textAutoComplete|textNoSuggestions"
            android:maxLines="1"
            android:paddingEnd="8dp"
            android:textColor="@android:color/black"
            android:textColorHint="@color/material_light_hint_text"
            android:textSize="20sp" />

        <ImageView
            android:id="@+id/search_close_btn"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:contentDescription="@string/abc_searchview_description_clear"
            android:focusable="true"
            android:paddingEnd="8dp"
            android:paddingStart="8dp" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/submit_area"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/search_go_btn"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:contentDescription="@string/abc_searchview_description_submit"
            android:focusable="true"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:visibility="gone" />

        <ImageView
            android:id="@+id/search_voice_btn"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center_vertical"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:contentDescription="@string/abc_searchview_description_voice"
            android:focusable="true"
            android:paddingEnd="8dp"
            android:paddingStart="8dp"
            android:visibility="gone" />
    </LinearLayout>
</LinearLayout>

Beachten Sie, dass ich die Anker-Dropdown-Ansicht unter der Toolbar-Ansicht hinzugefügt habe, sodass Vorschläge die volle Bildschirmbreite erhalten.

<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/appBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:collapseIcon="@drawable/ic_search_collapse"
    app:popupTheme="@style/AppTheme.PopupOverlay"
    app:theme="@style/ToolbarTheme" />

<View
    android:id="@+id/anchor_dropdown"
    android:layout_width="match_parent"
    android:layout_height="0dp" />

</android.support.design.widget.AppBarLayout>

search_view_suggestion_row.xml:

(ändern Sie die Sichtbarkeit von suggestion_divider, wenn Sie eine Trennlinie zwischen den Vorschlägen wünschen):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="58dp"
    android:theme="@style/Theme.AppCompat.DayNight">

<!-- Icons come first in the layout, since their placement doesn't depend on
     the placement of the text views. -->
<ImageView
    android:id="@android:id/icon1"
    style="@style/RtlOverlay.Widget.AppCompat.Search.DropDown.Icon1"
    android:layout_width="56dp"
    android:layout_height="56dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentTop="true"
    android:scaleType="centerInside"
    android:visibility="invisible" />

<ImageView
    android:id="@+id/edit_query"
    style="@style/RtlOverlay.Widget.AppCompat.Search.DropDown.Query"
    android:layout_width="56dp"
    android:layout_height="56dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentTop="true"
    android:background="?attr/selectableItemBackground"
    android:scaleType="centerInside"
    android:visibility="gone" />

<ImageView
    android:id="@id/android:icon2"
    style="@style/RtlOverlay.Widget.AppCompat.Search.DropDown.Icon2"
    android:layout_width="56dp"
    android:layout_height="56dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentTop="true"
    android:layout_alignWithParentIfMissing="true"
    android:scaleType="centerInside"
    android:visibility="gone" />

<!-- The subtitle comes before the title, since the height of the title depends on whether the
     subtitle is visible or gone. -->
<TextView
    android:id="@android:id/text2"
    style="?android:attr/dropDownItemStyle"
    android:layout_width="match_parent"
    android:layout_height="29dp"
    android:layout_alignParentBottom="true"
    android:layout_alignWithParentIfMissing="true"
    android:gravity="top"
    android:maxLines="1"
    android:paddingBottom="4dp"
    android:textColor="?android:textColorSecondary"
    android:textSize="12sp"
    android:visibility="gone" />

<!-- The title is placed above the subtitle, if there is one. If there is no
     subtitle, it fills the parent. -->
<TextView
    android:id="@android:id/text1"
    style="?android:attr/dropDownItemStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@android:id/text2"
    android:layout_centerVertical="true"
    android:ellipsize="end"
    android:maxLines="1"
    android:scrollHorizontally="false"
    android:textColor="?android:textColorPrimary"
    android:textSize="16sp" />

<View
    android:id="@+id/suggestion_divider"
    android:layout_width="match_parent"
    android:layout_height="0.5dp"
    android:layout_alignParentBottom="true"
    android:layout_alignStart="@android:id/text1"
    android:layout_marginStart="8dp"
    android:background="@color/divider_color"
    android:visibility="gone" />

Der Vorschlagshintergrund und das Commit-Symbol sind maßgefertigt, die restlichen Symbole, die ich verwendet habe, finden Sie unter: https://material.io/icons/

ic_search_commit.xml:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:autoMirrored="true"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:fillColor="@color/active_icon_color"
        android:pathData="m18.364,16.95l-8.605,-8.605l7.905,-0l-0.007,-2.001l-11.314,0l0,11.314l1.994,-0l0.007,-7.898l8.605,8.605l1.414,-1.414z" />

search_suggestions_bg.xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
    <shape android:shape="rectangle">
        <padding android:top="0.5dp" />
        <stroke
            android:width="0.5dp"
            android:color="@color/divider_color" />
    </shape>
</item>
<item>
    <shape android:shape="rectangle">
        <solid android:color="@color/cards_and_dialogs_color" />
    </shape>
</item>
</layer-list>

Fügen Sie Ihrer colors.xml folgende Werte hinzu (fügen Sie value-night nur hinzu, wenn Sie das DayNight-Design verwenden):

Werte/Farben.xml

<color name="material_light_primary_text">#DE000000</color>
<color name="material_light_hint_text">#61000000</color>
<color name="material_light_active_icon">#8A000000</color>
<color name="material_ripple_light">#1F000000</color>
<color name="divider_color">#1F000000</color>
<color name="active_icon_color">#8A000000</color>
<color name="cards_and_dialogs_color">@android:color/white</color>
<color name="quantum_grey_600">#757575</color>

Werte-Nacht/Farben.xml:

<color name="divider_color">#1FFFFFFF</color>
<color name="active_icon_color">@android:color/white</color>
<color name="cards_and_dialogs_color">#424242</color>

3) Letzter Teil, lassen Sie die Magie im Code geschehen:

Richten Sie SearchView in Ihrer gewünschten Aktivität ein und initialisieren Sie es

private MenuItem mSearchItem;
private Toolbar mToolbar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    mToolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(mToolbar);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);

    mSearchItem = menu.findItem(R.id.m_search);

    MenuItemCompat.setOnActionExpandListener(mSearchItem, new MenuItemCompat.OnActionExpandListener() {
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // Called when SearchView is collapsing
            if (mSearchItem.isActionViewExpanded()) {
                animateSearchToolbar(1, false, false);
            }
            return true;
        }

        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // Called when SearchView is expanding
            animateSearchToolbar(1, true, true);
            return true;
        }
    });

    return true;
}

public void animateSearchToolbar(int numberOfMenuIcon, boolean containsOverflow, boolean show) {

    mToolbar.setBackgroundColor(ContextCompat.getColor(this, android.R.color.white));
    mDrawerLayout.setStatusBarBackgroundColor(ContextCompat.getColor(this, R.color.quantum_grey_600));

    if (show) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            int width = mToolbar.getWidth() -
                    (containsOverflow ? getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_overflow_material) : 0) -
                    ((getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material) * numberOfMenuIcon) / 2);
            Animator createCircularReveal = ViewAnimationUtils.createCircularReveal(mToolbar,
                    isRtl(getResources()) ? mToolbar.getWidth() - width : width, mToolbar.getHeight() / 2, 0.0f, (float) width);
            createCircularReveal.setDuration(250);
            createCircularReveal.start();
        } else {
            TranslateAnimation translateAnimation = new TranslateAnimation(0.0f, 0.0f, (float) (-mToolbar.getHeight()), 0.0f);
            translateAnimation.setDuration(220);
            mToolbar.clearAnimation();
            mToolbar.startAnimation(translateAnimation);
        }
    } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            int width = mToolbar.getWidth() -
                    (containsOverflow ? getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_overflow_material) : 0) -
                    ((getResources().getDimensionPixelSize(R.dimen.abc_action_button_min_width_material) * numberOfMenuIcon) / 2);
            Animator createCircularReveal = ViewAnimationUtils.createCircularReveal(mToolbar,
                    isRtl(getResources()) ? mToolbar.getWidth() - width : width, mToolbar.getHeight() / 2, (float) width, 0.0f);
            createCircularReveal.setDuration(250);
            createCircularReveal.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    mToolbar.setBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimary));
                    mDrawerLayout.setStatusBarBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimaryDark));
                }
            });
            createCircularReveal.start();
        } else {
            AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
            Animation translateAnimation = new TranslateAnimation(0.0f, 0.0f, 0.0f, (float) (-mToolbar.getHeight()));
            AnimationSet animationSet = new AnimationSet(true);
            animationSet.addAnimation(alphaAnimation);
            animationSet.addAnimation(translateAnimation);
            animationSet.setDuration(220);
            animationSet.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {

                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    mToolbar.setBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimary));
                }

                @Override
                public void onAnimationRepeat(Animation animation) {

                }
            });
            mToolbar.startAnimation(animationSet);
        }
        mDrawerLayout.setStatusBarBackgroundColor(getThemeColor(MainActivity.this, R.attr.colorPrimaryDark));
    }
}

private boolean isRtl(Resources resources) {
    return resources.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}

private static int getThemeColor(Context context, int id) {
    Resources.Theme theme = context.getTheme();
    TypedArray a = theme.obtainStyledAttributes(new int[]{id});
    int result = a.getColor(0, 0);
    a.recycle();
    return result;
}

Einige Dinge, die am Code zu beachten sind:

1) Die Animation passt ihren Startpunkt basierend auf Ihrer Anzahl von Menüelementen an und wenn die Symbolleiste ein Überlaufsymbol hat, erkennt sie automatisch, ob das Layout LTR oder RTL ist.

2) Ich verwende die Aktivität der Navigationsleiste, also setze ich die StatusBar-Farbe auf mDrawerLayout. Wenn Sie regelmäßige Aktivitäten verwenden, können Sie die StatusBar-Farbe auf diese Weise festlegen:

getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.quantum_grey_600));

3) Die kreisförmige Enthüllungsanimation funktioniert nur auf KitKat und höher.

  • Das sieht toll aus, könntest du es vielleicht auf Github stellen? Wo Sie die Datei toolbar_search_view.xml erstellen, befindet sich diese appbarlayout-XML in derselben Datei?

    – zen_1991

    19. Januar 2017 um 7:10 Uhr

  • Ich habe hinzufügen circleReveal-Animation mit Bibliothek von Drittanbietern unter Lollipop Setzen Sie einfach die Symbolleiste in das Rahmenlayout io.codetail.widget.RevealFrameLayout und importieren Sie io.codetail.animation.ViewAnimationUtils anstelle der Android-Klasse und sehen Sie die Magie

    – Zohaib Akram

    1. Februar 2017 um 13:06 Uhr

  • Beachten Sie, dass toolbar_search_view.xml eine geänderte Kopie von abc_search_view.xml aus der Support-Bibliothek ist, die für Apache 2.0 lizenziert ist. Wenn Sie dies verwenden, sollten Sie also sicherstellen, dass Sie diese Lizenz einhalten.

    – Simon Warta

    21. Mai 2017 um 16:08 Uhr


  • „android:popupElevation“ funktioniert nur mit Android 5.0+. Aber ich brauche das für Android 4.3.

    – Alexej

    17. Oktober 2017 um 10:30 Uhr

  • Sie verwenden ein dunkles actionBar-Design, daher sind der Titel und die Symbole weiß (in Ihrem Beispiel auf einem hellblauen Hintergrund), aber wenn die Suche erweitert wird, sind die Farben jetzt grau. Wie erreichen Sie das? meins ist immer noch weiß, also ist es weiß auf weiß …

    – ndori

    15. August 2018 um 7:16 Uhr

Benutzer-Avatar
Jigar Brahmbhatt

Dies ist eigentlich ganz einfach, wenn Sie die Bibliothek android.support.v7 verwenden.

Schritt 1

Deklarieren Sie einen Menüpunkt

<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" />

Schritt 2

AppCompatActivity erweitern und im onCreateOptionsMenu die SearchView einrichten.

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;
    }

    ... 
}

  • Wie bekomme ich den Abfragetext?

    – cristianego

    8. Dezember 2017 um 1:56 Uhr

Die Idee ist sehr einfach – Sie müssen Ihre eigene AutoCompleteTextView mit EditText, TextWatcher und RecyclerView mit Filterable-Adapter schreiben.

  • EditText bietet Ihnen ein Textfeld mit der Möglichkeit, Zeichen einzugeben
  • Mit TextWatcher können Sie auf Textänderungen achten
  • RecyclerView kann überall platziert werden, sodass Sie die Suchergebnisse wie auf Ihrem Screenshot anzeigen können
  • Filterbarer Adapter hilft bei der Darstellung von Daten, die mit dem eingegebenen Text gefiltert sind

So:

  • Erstellen Sie ein Layout mit EditText oben, wobei RecyclerView den verbleibenden Platz ausfüllt. Fügen Sie das Symbol, den Schatten usw. hinzu.
  • Fügen Sie einen TextWatcher hinzu und aktualisieren Sie den Adapter bei jeder Textänderung

Wenn Sie meine Lösung in Aktion sehen möchten, schauen Sie sich mein Projekt auf Github an:
https://github.com/ZieIony/Carbon

Die Auto-Complete-Demo kann in der Beispiel-App im Abschnitt „Demos“ angehört werden.

Bildschirmfoto

  • Ich glaube du hast meine Frage falsch verstanden oder ich habe sie nicht richtig formuliert. Meine Frage bezog sich auf die Implementierung des UI-Teils und nicht auf die Textüberwachungs- und Filterlogik – ob Android Widgets (wie ActionBar, Menüelemente usw.) hat, die bei der Implementierung dieser Ansicht gemäß den Materialdesignrichtlinien helfen? Es stellt sich heraus, dass es keine solchen Widgets gibt und Sie die Symbolleiste selbst erstellen müssen. Sobald Sie dies herausgefunden haben, können wir Ihre Antwort verwenden, um die Filter- und Textüberwachungslogik zu erstellen. Obwohl ich Ihre Antwort positiv bewertet und für nützlich befunden habe, habe ich sie nicht akzeptiert, da sie nur einen Teil der Frage beantwortet.

    – GunnerFan

    7. August 2015 um 11:38 Uhr

Ausgehend von einem Hinweis aus der Antwort von @ Zielony habe ich Folgendes getan:

1) Stattdessen habe ich bei Verwendung einer ActionBar oder ToolBar mein eigenes Layout erstellt (im Grunde ein RelativeLayout mit Burger-Menü, Suche und anderen Menüschaltflächen und einem EditText für die Suche)

2) Ich habe ein Design ohne ActionBar verwendet und mein benutzerdefiniertes Layout oben in der Aktivität platziert, sodass es wie eine ActionBar aussah.

3) Im OnClickListener der Suchschaltfläche mache ich zwei Dinge:

  • Blenden Sie die Menüschaltflächen aus und zeigen Sie den ‘Such’-Bearbeitungstext an.
  • Fügen Sie ein Fragment hinzu, um Suchvorschläge anzuzeigen und zu suchen
  • Zeigen Sie die Softkeyboard-Eingabe an

3) OnClickListeners für die anderen Menüschaltflächen hinzugefügt.

4) Einen TextWatcher auf der „Suche“ EditText hinzugefügt, um Suchhinweise und Ergebnisse vom Server anzuzeigen.

So sieht es jetzt aus:
Geben Sie hier die Bildbeschreibung ein

Ich glaube, ich habe es herausgefunden. Ich verwende jetzt nur einen EditText innerhalb der Symbolleiste.

Ich habe jetzt das:

Geben Sie hier die Bildbeschreibung ein

Zuerst habe ich in onCreate() meiner Aktivität den EditText mit einer Bildansicht auf der rechten Seite wie folgt zur Symbolleiste hinzugefügt:

// 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
    // http://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) {
        // http://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);

Das hat funktioniert, aber dann bin ich auf ein Problem gestoßen, bei dem onOptionsItemSelected() nicht aufgerufen wurde, als ich auf die Home-Schaltfläche getippt habe. Daher konnte ich die Suche nicht durch Drücken der Home-Taste abbrechen. Ich habe verschiedene Möglichkeiten ausprobiert, den Klick-Listener auf der Home-Schaltfläche zu registrieren, aber sie haben nicht funktioniert.

Irgendwann fand ich heraus, dass der ActionBarDrawerToggle, den ich hatte, die Dinge störte, also habe ich ihn entfernt. Dieser Listener begann dann zu arbeiten:

 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));
    }
});

So kann ich jetzt die Suche mit dem Home-Button abbrechen, aber ich kann noch nicht den Zurück-Button drücken, um sie abzubrechen. Also habe ich dies zu onBackPressed() hinzugefügt:

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;
    }
}

Ich habe diese Methode erstellt, um die Sichtbarkeit des EditText- und Menüelements umzuschalten:

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);
    }
}

Ich brauchte eine Möglichkeit, die Home-Schaltfläche in der Symbolleiste zwischen dem Schubladensymbol und der Zurück-Schaltfläche umzuschalten. Ich habe schließlich die folgende Methode in dieser SO-Antwort gefunden. Obwohl ich es leicht modifiziert habe, um es für mich sinnvoller zu machen:

private enum ActionDrawableState
{
  BURGER, ARROW 
}

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);
        }
    }
}

Das funktioniert, ich habe es geschafft, ein paar Fehler zu beheben, die ich auf dem Weg gefunden habe. Ich glaube nicht, dass es 100% ist, aber es funktioniert gut genug für mich. BEARBEITEN: Wenn Sie die Suchansicht in XML anstelle von Java hinzufügen möchten, tun Sie dies:

Symbolleiste.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="https://stackoverflow.com/questions/30369246/@drawable/ic_close_white_24dp" />
</LinearLayout>

onCreate() Ihrer Aktivität:

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
    // http://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);

Benutzer-Avatar
ShahrozKhan91

Hier ist, wie ich versucht habe, es zu implementieren, bitte überprüfen Sie dies.

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

Meterial Search View

Benutzer-Avatar
Gemeinschaft

Sie können AutoCompleteTextView verwenden, um dies zu erreichen, folgen Sie dem Link unten

Wie erstelle ich ein Gmail-ähnliches Suchfeld in der Aktionsleiste?

  • Ich habe das schon. Ich möchte es gemäß den Materialdesignrichtlinien implementieren. Beachten Sie, wie Vorschläge in der Hauptansicht statt in der Dropdown-Liste angezeigt werden.

    – GunnerFan

    21. Mai 2015 um 9:28 Uhr

1176100cookie-checkImplementieren von SearchView gemäß den Material Design Guidelines

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy