Creazione di un SearchView che assomiglia alle linee guida di progettazione del materiale


134

Attualmente sto imparando come convertire la mia app in Material design e al momento sono un po 'bloccato. Ho aggiunto la barra degli strumenti e ho fatto sovrapporre tutto il contenuto al mio cassetto di navigazione.

Ora sto cercando di creare una ricerca espandibile che assomigli a quella delle linee guida sui materiali : inserisci qui la descrizione dell'immagine

questo è quello che ho in questo momento e non riesco a capire come renderlo come sopra:
La mia ricerca

Questo è il mio menu xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_search"
        android:icon="@android:drawable/ic_menu_search"
        android:title="Search"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

Funziona, ottengo una voce di menu che si espande in SearchView e posso filtrare bene il mio elenco. Tuttavia, non assomiglia affatto alla prima foto.

Ho cercato di usare MenuItemCompat.setOnActionExpandListener()il R.id.action_searchcosì ho potuto cambiare l'icona sede di una freccia indietro, ma questo non sembra funzionare. Niente viene sparato nell'ascoltatore. Anche se funzionasse, non sarebbe comunque molto vicino alla prima immagine.

Come faccio a creare un SearchView nella nuova barra degli strumenti di appcompat che assomiglia alle linee guida sui materiali?


6
app: showAsAction = "sempre | collapseActionView"
Pavlos il

Si potrebbe voler dare un'occhiata alla mia risposta qui: stackoverflow.com/a/41013994/5326551
shnizlon

Risposte:


152

In realtà è abbastanza facile farlo, se si utilizza la android.support.v7libreria.

Passo 1

Dichiarare una voce di menu

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

Passo 2

Estendi AppCompatActivitye nella onCreateOptionsMenuconfigurazione di 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;
    }

    ... 

}

Risultato

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


2
L'avevo votato, ma quale emulatore stai usando? L'ho provato ma non ricevo il navigate-backpulsante, ma piuttosto un'icona di ricerca, e la sua distanza dal bordo sinistro dello schermo non è la stessa tra l' Xicona e il bordo destro dello schermo (non ho overflow dell'azione). Hai inserito la domanda qui , puoi esaminarla?
Solace,

13
non è una ricerca materiale. è solo la solita vecchia ricerca nella barra delle azioni
Gopal Singh Sirvi,

2
Ho risposto alla mia sotto-domanda, per renderla sempre visibile senza la necessità di fare clic sul pulsante di ricerca per aggiungere la linea searchView.setIconifiedByDefault(false);alla onCreateOptionsMenufunzione.
adelriosantiago,

3
un altro utile bocconcino - se si desidera espandere inizialmente la vista di ricerca assicurarsi di averlo fatto app:showAsAction="always"e NONapp:showAsAction="ifRoom|collapseActionView"
Vinay W

1
Inoltre, usando questo metodo, anche quando la barra di ricerca viene espansa, OverflowIcon è ancora visibile (ovvero i 3 punti). Ma alcune app gestiscono la ricerca espandendola completamente e cambiando lo sfondo in bianco. Come GMail
Zen

83

Dopo una settimana di perplessità su questo. Penso di averlo capito.
Ora sto usando solo un EditText all'interno della barra degli strumenti. Questo mi è stato suggerito da oj88 su reddit.

Ora ho questo:
Nuova SearchView

prima su onCreate () della mia attività ho aggiunto EditText con una vista immagine sul lato destro della barra degli strumenti in questo modo:

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

Questo ha funzionato, ma poi ho riscontrato un problema in cui onOptionsItemSelected () non veniva chiamato quando ho toccato il pulsante Home. Quindi non sono stato in grado di annullare la ricerca premendo il pulsante Home. Ho provato alcuni modi diversi di registrare il listener di clic sul pulsante Home ma non hanno funzionato.

Alla fine ho scoperto che ActionBarDrawerToggle che avevo interferiva con le cose, quindi l'ho rimosso. Questo ascoltatore ha quindi iniziato a funzionare:

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

Quindi ora posso annullare la ricerca con il pulsante Home, ma non posso premere il pulsante Indietro per annullarla ancora. Quindi l'ho aggiunto a onBackPressed ():

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

Ho creato questo metodo per attivare la visibilità di EditText e della voce di menu:

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

Avevo bisogno di un modo per alternare il pulsante Home sulla barra degli strumenti tra l'icona del cassetto e il pulsante Indietro. Alla fine ho trovato il metodo seguente in questa risposta SO . Anche se l'ho modificato leggermente per avere più senso per me:

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

Funziona, sono riuscito a risolvere alcuni bug che ho trovato lungo la strada. Non credo sia al 100% ma funziona abbastanza bene per me.

MODIFICA: Se si desidera aggiungere la vista di ricerca in XML anziché Java, procedere come segue:

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 () della tua attività:

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

Funziona alla grande, sembra fantastico, grazie! Tuttavia, invece di creare i layout nel codice, ho creato LinearLayout con EditText e ImageView in xml e l'ho solo gonfiato in onCreate.
aluxian

Sì, ho provato a farlo in XML ma pensavo di fare qualcosa di sbagliato in quanto Android Studio non mi avrebbe dato il completamento automatico nel layout XML.
Mike,

Potete per favore aggiornare questa risposta con il rispettivo design del layout XML richiesto per questo? questo può aiutare gli altri molto bene.
Shreyash Mahajan,

1
@Mike Puoi aggiornare la tua risposta e inserire il tuo codice sorgente github completo?
Hamed Ghadirian,

1
per favore pubblica il progetto completo in github
Nilabja il


19

Il primo screenshot nella tua domanda non è un widget pubblico. Il supporto SearchView ( android.support.v7.widget.SearchView) imita SearchView di Android 5.0 Lollipop (android.widget.SearchView . Il tuo secondo screenshot viene utilizzato da altre app progettate come Google Play.

SearchView nel tuo primo screenshot viene utilizzato in Drive, YouTube e altri Google Apps chiusi. Fortunatamente, viene utilizzato anche in Android 5.0 Dialer . Puoi provare a eseguire il backport della vista, ma utilizza alcune API 5.0.

Le classi che vorrai guardare sono:

SearchEditTextLayout , AnimUtils e DialtactsActivity per capire come usare la vista. Avrai anche bisogno di risorse da ContactsCommon .

Buona fortuna.


Grazie per averlo esaminato, speravo che ci fosse già qualcosa là fuori che potesse farlo. Per ora ho appena usato un EditText con uno sfondo trasparente e sembra ok per quello che mi serve.
Mike,

111
Questa risposta è molto inquietante per me. Perché Google utilizza un widget privato che coincide con le proprie linee guida di progettazione dei materiali e quindi pubblica un widget scadente per noi che non lo fa? E ogni sviluppatore è ora là fuori alle prese con questo da solo? Quale possibile ragionamento per questo?
Greg Ennis,

18

Ecco il mio tentativo di farlo:

Passaggio 1: crea uno stile denominato 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>

Passaggio 2: creare un layout denominato 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" />  

Passaggio 3: creare una voce di menu per questa vista di ricerca

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

Passaggio 4: gonfiare il menu

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

Risultato:

inserisci qui la descrizione dell'immagine

L'unica cosa che non sono riuscito a fare è stata quella di riempire l'intera larghezza del file Toolbar. Se qualcuno potesse aiutarmi a farlo, sarebbe dorato.


1
I wasn't able to do was to make it fill the entire width, quale versione della libreria di supporto stai utilizzando? Prova a impostare la app:contentInsetStartWithNavigation="0dp"tua barra degli strumenti.
Mangesh,

@LittleChild, prova la soluzione fornita da Magnesh. Se il problema persiste, prova ad aggiungere le righe seguenti nella barra degli strumenti. app: contentInsetStartWithNavigation = App "0dp": contentInsetLeft = "0dp" app: contentInsetStart = "0dp" app: paddingStart = "0dp" android: layout_marginLeft = "0dp" android: layout_marginStart = "0dp"
Shreyash Mahajan

Grazie per aver messo la spiegazione per ogni riga in SearchViewStyle!
Shinta S,

Piccolo Bambino Per tutta la larghezza, si può fare sth come questo: (" stackoverflow.com/questions/27946569/... )
Ali_dev

10

Per ottenere l'aspetto desiderato di SearchView, puoi utilizzare gli stili.

Innanzitutto, devi creare styleper SearchView, che dovrebbe assomigliare a questo:

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

Intero elenco di attributi che puoi trovare in questo articolo, nella sezione "SearchView".

In secondo luogo, è necessario creare un styleper il tuo Toolbar, che viene utilizzato come ActionBar:

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

Infine, devi aggiornare l'attributo del tema della barra degli strumenti in questo modo:

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

Risultato:

inserisci qui la descrizione dell'immagine

NOTA: è necessario modificare Toolbardirettamente l'attributo del tema. Se aggiorni solo l' searchViewStyleattributo del tema principale , ciò non influirà sul tuo Toolbar.


Ehi, hai aggiunto tu quelle navigate-back(freccia indietro) e cancel(le x) icone o sono state aggiunte automaticamente?
Solace,

1
@Solace vengono aggiunti automaticamente
Artem

Appaiono solo quando inizi a scrivere la query di ricerca in SearchView o sono presenti anche quando non hai scritto nulla e il suggerimento di ricerca è visibile? Sto chiedendo perché il mio non viene visualizzato fino a quando non inizio a scrivere la query. Quindi questa informazione sarà molto utile per me
Solace,

1
@Solace navigate-backviene sempre mostrato, clearviene mostrato solo dopo aver scritto una query di ricerca.
Artem,

6

Un altro modo per ottenere l'effetto desiderato è utilizzare questa libreria della vista Ricerca materiale . Gestisce automaticamente la cronologia delle ricerche ed è anche possibile fornire suggerimenti di ricerca alla vista.

Esempio: (è mostrato in portoghese, ma funziona anche in inglese e italiano).

Campione

Impostare

Prima di poter utilizzare questa libreria, è necessario implementare una classe denominata MsvAuthorityall'interno del br.com.maukerpacchetto sul modulo dell'app e deve disporre di una variabile String statica pubblica chiamata CONTENT_AUTHORITY. Dagli il valore che desideri e non dimenticare di aggiungere lo stesso nome al tuo file manifest. La lib utilizzerà questo file per impostare l'autorità del provider di contenuti.

Esempio:

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>

uso

Per usarlo, aggiungi la dipendenza:

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

E quindi, nel tuo Activityfile di layout, aggiungi quanto segue:

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

Successivamente, dovrai solo ottenere il MaterialSearchViewriferimento utilizzando getViewById()e aprirlo o chiuderlo utilizzando MaterialSearchView#openSearch()e MaterialSearchView#closeSearch().

PS: è possibile aprire e chiudere la vista non solo da Toolbar. Puoi utilizzare il openSearch()metodo praticamente da qualsiasi Button, come un pulsante di azione mobile.

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

Puoi anche chiudere la vista usando il pulsante Indietro, procedendo come segue:

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

Per maggiori informazioni su come usare la lib, controlla la pagina di github .


2
Ottima libreria e ottima idea per astrarre il metodo open / close in modo che un MenuItem non sia richiesto per aprirlo / chiuderlo, ho intenzione di usarlo nella mia app con un FloatingActionButton con un'icona di ricerca, quindi funzionerà alla grande.
AdamMc331,

Perché non ci sono parametri per stringhe come "Cerca"? Sembra che la biblioteca limiti le persone alla versione inglese o portoghese della stringa: /
Aspiring Dev

Ma è possibile cambiare il suggerimento String usando gli stili come indicato nel README. Per quanto riguarda il suggerimento per l'input vocale, verrà rilasciato in seguito: github.com/Mauker1/MaterialSearchView/issues/23
Mauker,

@rpgmaker Controlla l'ultimo aggiornamento, ora è possibile cambiare quelle stringhe.
Mauker,

@Mauker hai idea di come impostare Android: imeOptions = "actionSearch" sul EditText del tuo componente? (Voglio visualizzare un pulsante "cerca" sulla tastiera)
Greg

2

Quanto segue creerà un SearchView identico a quello in Gmail e lo aggiungerà alla barra degli strumenti fornita. Dovrai solo implementare il tuo metodo "ViewUtil.convertDpToPixel".

private SearchView createMaterialSearchView(Toolbar toolbar, String hintText) {

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

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

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

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

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

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

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

    return searchView;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.