webentwicklung-frage-antwort-db.com.de

Implementieren von SearchView gemäß den Richtlinien für das Materialdesign

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

Wenn Sie auf das Suchsymbol klicken, wird die gesamte Symbolleiste so animiert, dass nur der Suchtext mit weißem Hintergrund und Vorschlägen in der Hauptansicht anstelle eines Dropdowns angezeigt wird.

Hier ist ein Screenshot aus den Richtlinien: enter image description here

Hier ist ein GIF aus der Implementierung von Gmail Inbox: enter image description here

Ich habe nach Codebeispielen und Tutorials gesucht, aber bisher war ich nicht erfolgreich. Wie gehe ich um dies zu tun?

36
GunnerFan

Ich habe mehrere SearchView-Materialbibliotheken ausprobiert, aber keine davon hat gut funktioniert wie die der Supportbibliothek. Deshalb habe ich beschlossen, sie neu zu gestalten. Nach viel Arbeit bin ich mit dem Ergebnis zufrieden:

enter image description here

So können Sie es machen:

1) Fügen Sie SearchView 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 actionLayout anstelle von actionViewClass deklariere Dies ist die einzige Möglichkeit, das SearchView-Design vom Toolbar-Design zu trennen.

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 Ihren Stilen hinzu, und 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 Symbolleistenansicht hinzugefügt habe, damit 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 zwischen Vorschlägen unterscheiden möchten.):

<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 Hintergrund der Vorschläge und das Festschreibungssymbol sind Sonderanfertigungen. Die restlichen von mir verwendeten Symbole 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 die folgenden Werte hinzu (fügen Sie values-night nur hinzu, wenn Sie das DayNight-Design verwenden):

values ​​/ colors.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>

values-night/colors.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, lass die Magie im Code geschehen:

Richten Sie SearchView in der 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 Sie über den Code beachten sollten:

1) Die Animation passt den Startpunkt basierend auf der Anzahl der Menüelemente an. Wenn die Symbolleiste über ein Überlaufsymbol verfügt, wird automatisch erkannt, ob das Layout LTR oder RTL ist.

2) Ich verwende die Aktivität der Navigationsleiste, daher setze ich die Farbe der Statusleiste auf mDrawerLayout. Wenn Sie die normale Aktivität verwenden, können Sie die Farbe der Statusleiste folgendermaßen festlegen:

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

3) Die Animation der kreisförmigen Enthüllung funktioniert nur mit KitKat und höher.

100
shnizlon

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

Erweitern Sie AppCompatActivity und richten Sie im onCreateOptionsMenu die SearchView ein.

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

    ... 
}
9

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, in das Sie Zeichen eingeben können
  • Mit TextWatcher können Sie nach Textänderungen suchen
  • RecyclerView kann überall platziert werden, sodass Sie die Suchergebnisse genau wie auf Ihrem Screenshot anzeigen können
  • Filterbarer Adapter hilft bei der Darstellung von Daten, die mit dem eingegebenen Text gefiltert wurden

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-Vervollständigung-Demo kann in der Beispiel-App im Abschnitt "Demos" abgespielt werden.

Screenshot

8
Zielony

Unter Berücksichtigung eines Hinweises auf @ Zielonys Antwort habe ich Folgendes getan:

1) Wenn ich stattdessen eine ActionBar oder ToolBar verwende, habe ich mein eigenes Layout erstellt (im Grunde genommen ein RelativeLayout mit Burger-Menü, Such- und anderen Menüschaltflächen und einem EditText für die Suche).

2) Bei Verwendung eines Themas ohne ActionBar wurde mein benutzerdefiniertes Layout am Anfang 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 'Search'-EditText an.
  • Fügen Sie ein Fragment hinzu, um Suchvorschläge und -ergebnisse anzuzeigen
  • Zeigen Sie die Softtastatureingabe an

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

4) Es wurde ein TextWatcher zum 'Suchen' von EditText hinzugefügt, um Suchtipps und Ergebnisse vom Server anzuzeigen.

So sieht es jetzt aus: enter image description here

7
GunnerFan

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

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

Meterial Search View

2
ShahrozKhan91

Ich glaube, ich habe es herausgefunden. Ich verwende jetzt nur einen EditText in der Toolbar.

Ich habe jetzt folgendes:

enter image description here

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 tippte. Daher konnte ich die Suche nicht durch Drücken der Home-Taste abbrechen. Ich habe verschiedene Möglichkeiten ausprobiert, um den Klicklistener auf der Startseite zu registrieren, aber sie haben nicht funktioniert.

Schließlich stellte ich fest, dass der ActionBarDrawerToggle, den ich hatte, die Dinge störte, und entfernte ihn. Dieser Listener fing dann an 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 der Home-Taste abbrechen, aber ich kann die Zurück-Taste noch nicht 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 von EditText und Menüpunkt 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 fand schließlich die Methode unten in dieser Antwort SO. Obwohl ich sie leicht modifiziert habe, um mir mehr Sinn 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 auszuräumen, die ich auf dem Weg gefunden habe. Ich denke 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, gehen Sie folgendermaßen vor:

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>

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

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

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

0
Vinay Jayaram