Erstellen einer Suchansicht, die den Richtlinien für das Materialdesign entspricht

134

Ich bin gerade dabei zu lernen, wie ich meine App in Materialdesign konvertiere, und ich bin gerade ein bisschen festgefahren. Ich habe die Symbolleiste hinzugefügt und meine Navigationsschublade über den gesamten Inhalt gelegt.

Ich versuche jetzt, eine erweiterbare Suche zu erstellen, die der in den Materialrichtlinien entspricht : Geben Sie hier die Bildbeschreibung ein

Dies ist, was ich gerade habe, und ich kann nicht herausfinden, wie ich es wie oben machen kann:
Meine Suche

Dies ist mein Menü 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>

Das funktioniert, ich bekomme einen Menüpunkt, der in die Suchansicht erweitert wird, und ich kann meine Liste gut filtern. Es sieht allerdings nicht wie das erste Bild aus.

Ich habe versucht , zu verwenden , MenuItemCompat.setOnActionExpandListener()auf , R.id.action_searchdamit ich die Home - Symbol auf einen Zurück - Pfeil ändern könnte, aber das scheint nicht zu funktionieren. Im Hörer wird nichts abgefeuert. Selbst wenn das funktionieren würde, wäre es dem ersten Bild nicht sehr nahe.

Wie erstelle ich eine Suchansicht in der neuen Appcompat-Symbolleiste, die den Materialrichtlinien entspricht?

Mike
quelle
6
App: showAsAction = "immer | kollabierenActionView"
Pavlos
Vielleicht möchten Sie einen Blick auf meine Antwort hier werfen
shnizlon

Antworten:

152

Dies ist eigentlich recht einfach, wenn Sie eine android.support.v7Bibliothek 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 AppCompatActivityund im onCreateOptionsMenuSetup die 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;
    }

    ... 

}

Ergebnis

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Subin Sebastian
quelle
2
Ich hatte es positiv bewertet, aber welchen Emulator verwenden Sie? Ich habe es versucht, aber ich erhalte nicht die navigate-backSchaltfläche, sondern ein Suchsymbol, und der Abstand vom linken Bildschirmrand entspricht nicht dem zwischen dem XSymbol und dem rechten Bildschirmrand (habe ich nicht) Aktionsüberlauf). Habe die Frage hier gepostet , kannst du sie dir ansehen?
Trost
13
Es ist keine materielle Suche. Es ist nur die übliche alte Suche in der
Aktionsleiste
2
Ich habe meine eigene Unterfrage beantwortet, um sie immer sichtbar zu machen, ohne auf die Suchschaltfläche klicken zu müssen. Fügen Sie searchView.setIconifiedByDefault(false);der onCreateOptionsMenuFunktion die Zeile hinzu .
Adelriosantiago
3
ein weiterer nützlicher Leckerbissen - wenn Sie möchten, dass die Suchansicht zunächst erweitert wird, stellen Sie sicher, dass Sie app:showAsAction="always"und NICHTapp:showAsAction="ifRoom|collapseActionView"
Vinay W
1
Bei Verwendung dieser Methode ist das OverflowIcon auch dann noch sichtbar, wenn die Suchleiste erweitert wird (dh die 3 Punkte). Einige Apps übernehmen jedoch die Suche, indem sie sie vollständig erweitern und den Hintergrund in Weiß ändern. Wie GMail
Zen
83

Nach einer Woche voller Rätsel. Ich glaube, ich habe es herausgefunden.
Ich verwende jetzt nur einen EditText in der Symbolleiste. Dies wurde mir von oj88 auf reddit vorgeschlagen.

Ich habe jetzt
Neue Suchansicht

Folgendes : Zuerst habe ich in onCreate () meiner Aktivität den EditText mit einer Bildansicht auf der rechten Seite zur Symbolleiste wie folgt 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
        // 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);

Dies funktionierte, aber dann stieß ich auf ein Problem, 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 Klick-Listener auf der Home-Schaltfläche zu registrieren, aber sie haben nicht funktioniert.

Schließlich fand ich heraus, dass der ActionBarDrawerToggle, den ich hatte, die Dinge störte, also entfernte ich ihn. 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 die Suche jetzt 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 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 Schubladen-Symbol und der Zurück-Schaltfläche umzuschalten. Ich fand schließlich die Methode unten in dieser SO-Antwort . Obwohl ich es leicht modifiziert habe, um für mich sinnvoller zu sein:

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

Dies funktioniert, ich habe es geschafft, ein paar Fehler herauszufinden, 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>
</android.support.v7.widget.Toolbar>

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
        // 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);
Mike
quelle
Funktioniert super, sieht gut aus, danke! Anstatt die Layouts im Code zu erstellen, habe ich das LinearLayout mit dem EditText und der ImageView in XML erstellt und es einfach in onCreate aufgeblasen.
Aluxian
Ja, ich habe versucht, dies in XML zu tun, aber ich dachte, ich mache etwas falsch, da Android Studio mir keine automatische Vervollständigung im Layout-XML ermöglicht.
Mike
Können Sie diese Antwort bitte mit dem dafür erforderlichen XML-Layout aktualisieren? das kann anderen sehr gut helfen.
Shreyash Mahajan
1
@Mike Kannst du bitte deine Antwort aktualisieren und deinen vollständigen Github-Quellcode eingeben?
Hamed Ghadirian
1
Bitte posten Sie das komplette Projekt in Github
Nilabja
22

Ich weiß, dass es ein alter Thread ist, aber ich poste immer noch die Bibliothek, die ich gerade erstellt habe. Hoffe das könnte jemandem helfen.

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

Meterial Search View

ShahrozKhan91
quelle
1
Es ist nicht schwer, aber ich mag deine Arbeit. Es spart mir Zeit, meine eigene Suchansicht zu erstellen. Dank bro!
Slim_user71169
19

Der erste Screenshot in Ihrer Frage ist kein öffentliches Widget. Die Unterstützung von SearchView ( android.support.v7.widget.SearchView) ahmt SearchView ( ) von Android 5.0 Lollipop nach android.widget.SearchView. Ihr zweiter Screenshot wird von anderen materiell gestalteten Apps wie Google Play verwendet.

Die Suchansicht in Ihrem ersten Screenshot wird in Drive, YouTube und anderen Closed-Source-Google Apps verwendet. Glücklicherweise wird es auch im Android 5.0 Dialer verwendet . Sie können versuchen, die Ansicht zurück zu portieren, sie verwendet jedoch einige 5.0-APIs.

Die Klassen, die Sie sich ansehen möchten, sind:

SearchEditTextLayout , AnimUtils und DialtactsActivity, um zu verstehen, wie die Ansicht verwendet wird. Sie benötigen außerdem Ressourcen von ContactsCommon .

Viel Glück.

Jared Rummler
quelle
Vielen Dank, dass Sie sich das angeschaut haben. Ich hatte gehofft, dass es da draußen schon etwas gibt, das das kann. Im Moment habe ich gerade einen EditText mit transparentem Hintergrund verwendet und es scheint in Ordnung für das zu sein, was ich brauche.
Mike
111
Diese Antwort ist für mich sehr beunruhigend. Warum verwendet Google ein privates Widget, das zufällig seiner eigenen Materialdesign-Richtlinie entspricht, und veröffentlicht dann ein beschissenes Widget für uns, das dies nicht tut? Und jeder Entwickler hat jetzt alleine damit zu kämpfen? Welche möglichen Gründe dafür?
Greg Ennis
18

Hier ist mein Versuch, dies zu tun:

Schritt 1: Erstellen Sie einen Stil mit dem Namen 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>

Schritt 2: Erstellen Sie ein Layout mit dem Namen 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" />  

Schritt 3: Erstellen Sie einen Menüpunkt für diese Suchansicht

<?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>  

Schritt 4: Blasen Sie das Menü auf

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

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Das einzige, was ich nicht konnte, war, es die gesamte Breite des zu füllen Toolbar. Wenn mir jemand dabei helfen könnte, wäre das golden.

Ein SO-Benutzer
quelle
1
I wasn't able to do was to make it fill the entire width, welche Support-Bibliotheksversion verwenden Sie? Versuchen Sie, Einstellungen app:contentInsetStartWithNavigation="0dp"für Ihre Symbolleiste vorzunehmen.
Mangesh
@LittleChild, probieren Sie die Lösung von Magnesh. Wenn es immer noch nicht gelöst wird, versuchen Sie, die folgenden Zeilen in die Symbolleiste einzufügen. App: contentInsetStartWithNavigation = "0dp" App: contentInsetLeft = "0dp" App: contentInsetStart = "0dp" App: paddingStart = "0dp" android: layout_marginLeft = "0dp" android: layout_marginStart = "0dp"
Shreyash Mahajan
Vielen Dank für die Erklärung für jede Zeile in SearchViewStyle!
Shinta S
Kleines Kind Für die gesamte Breite können Sie Folgendes tun: (" stackoverflow.com/questions/27946569/… )
Ali_dev
10

Um das gewünschte Aussehen von SearchView zu erzielen, können Sie Stile verwenden.

Zuerst müssen Sie stylefür Ihre SearchView erstellen, die ungefähr so ​​aussehen sollte:

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

Eine vollständige Liste der Attribute finden Sie in diesem Artikel im Abschnitt "SearchView".

Zweitens müssen Sie eine stylefür Ihre erstellen Toolbar, die als ActionBar verwendet wird:

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

Und schließlich müssen Sie Ihr Toolbar-Designattribut folgendermaßen aktualisieren:

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

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

HINWEIS: Sie müssen Ihr ToolbarDesignattribut direkt ändern . Wenn Sie nur Ihr Hauptthemaattribut aktualisieren searchViewStyle, hat dies keine Auswirkungen auf Ihr Toolbar.

Artem
quelle
Hey, hast du diese navigate-back(Pfeil nach hinten) und cancel(die x) Symbole selbst hinzugefügt oder sie wurden automatisch hinzugefügt?
Trost
1
@Solace sie werden automatisch hinzugefügt
Artem
Werden sie nur angezeigt, wenn Sie mit dem Schreiben der Suchabfrage in der Suchansicht beginnen, oder sind sie auch dann vorhanden, wenn Sie nichts geschrieben haben und der Suchhinweis sichtbar ist? Ich frage, weil meine erst erscheinen, wenn ich mit dem Schreiben der Abfrage beginne. Diese Informationen werden für mich sehr nützlich sein
Trost
1
@Solace navigate-backwird immer angezeigt, clearwird erst angezeigt, nachdem Sie eine Suchabfrage geschrieben haben.
Artem
6

Eine andere Möglichkeit, den gewünschten Effekt zu erzielen, ist die Verwendung dieser Bibliothek für die Materialsuchansicht . Der Suchverlauf wird automatisch verarbeitet, und es können auch Suchvorschläge für die Ansicht bereitgestellt werden.

Beispiel: (Es wird auf Portugiesisch gezeigt, funktioniert aber auch auf Englisch und Italienisch).

Stichprobe

Konfiguration

Bevor Sie diese Bibliothek verwenden können, müssen Sie eine Klasse mit dem Namen MsvAuthorityinnerhalb des br.com.maukerPakets in Ihrem App-Modul implementieren , und es sollte eine öffentliche statische String-Variable namens aufgerufen werden CONTENT_AUTHORITY. Geben Sie ihm den gewünschten Wert und vergessen Sie nicht, Ihrer Manifestdatei denselben Namen hinzuzufügen. Die Bibliothek verwendet diese Datei, um die Berechtigung des Inhaltsanbieters festzulegen.

Beispiel:

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>

Verwendung

Fügen Sie zur Verwendung die Abhängigkeit hinzu:

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

Fügen Sie dann in Ihrer ActivityLayoutdatei Folgendes hinzu:

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

Danach müssen Sie nur das bekommen MaterialSearchViewReferenz unter Verwendung getViewById(), und öffnen Sie es oder schließen Sie es mit MaterialSearchView#openSearch()und MaterialSearchView#closeSearch().

PS: Es ist möglich, die Ansicht nicht nur von der zu öffnen und zu schließen Toolbar. Sie können die openSearch()Methode grundsätzlich von jedem beliebigen verwenden Button, z. B. einer schwebenden Aktionsschaltfläche.

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

Sie können die Ansicht auch über die Schaltfläche Zurück schließen, indem Sie folgende Schritte ausführen:

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

Weitere Informationen zur Verwendung der Bibliothek finden Sie auf der Github-Seite .

Mauker
quelle
2
Hervorragende Bibliothek und großartige Idee, die Open / Close-Methode so zu abstrahieren, dass kein MenuItem zum Öffnen / Schließen erforderlich ist. Ich plane, diese in meiner App mit einem FloatingActionButton mit einem Suchsymbol zu verwenden, damit sie hervorragend funktioniert.
AdamMc331
Warum gibt es keine Parameter für Zeichenfolgen wie "Suchen"? Es scheint , die Bibliothek Grenzen Menschen entweder in Englisch oder Portugiesisch Versionen des string: /
Aspiring Dev
Es ist jedoch möglich, den Hinweis-String mithilfe von Stilen zu ändern, wie in der README-Datei angegeben. Der Hinweis zur Spracheingabe wird später veröffentlicht: github.com/Mauker1/MaterialSearchView/issues/23
Mauker
@rpgmaker Überprüfen Sie das neueste Update. Es ist jetzt möglich, diese Zeichenfolgen zu ändern.
Mauker
@Mauker eine Idee, wie man android: imeOptions = "actionSearch" auf den EditText Ihrer Komponente setzt? (Ich möchte eine "Such" -Schaltfläche auf der Tastatur anzeigen)
Greg
2

Im Folgenden wird eine Suchansicht erstellt, die mit der in Google Mail identisch ist, und zur angegebenen Symbolleiste hinzugefügt. Sie müssen nur Ihre eigene "ViewUtil.convertDpToPixel" -Methode implementieren.

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

quelle