Skip to content

Implementazione di SearchView secondo le linee guida per la progettazione dei materiali

Non hai più bisogno di cercare su Internet poiché sei nel sito necessario, abbiamo la soluzione di cui hai bisogno ma senza essere coinvolto.

Soluzione:

Ho provato diverse librerie di materiali per SearchView, ma nessuna funzionava bene come quella della libreria di supporto, quindi ho deciso di riprogettarla; dopo molto lavoro, sono soddisfatto del risultato:

Immettere la descrizione dell'immagine qui

Ecco come si può fare:

1) Aggiungere la voce SearchView al menu


Notate che sto dichiarando actionLayout invece di actionViewClass Ho pensato che questo fosse l'unico modo per impostare il tema di SearchView separatamente dal tema della barra degli strumenti.

search_view_layout.xml:


2) Aggiungere il tema SearchView personalizzato agli stili e dichiarare il tema SearchView anche nel tema della barra degli strumenti:






toolbar_search_view.xml:










    

    
    

        

        
    

    

        

        
    

Si noti che ho aggiunto la vista a discesa dell'ancora sotto la vista della barra degli strumenti, in modo che i suggerimenti abbiano l'intera larghezza dello schermo.








search_view_suggestion_row.xml:

(cambiare la visibilità di suggestion_divider se si vuole un divisorio tra i suggerimenti):

















Lo sfondo dei suggerimenti e l'icona del commit sono fatti su misura, il resto delle icone che ho usato può essere trovato su: https://material.io/icons/

ic_search_commit.xml:


    

search_suggestions_bg.xml:



    
        
        
    


    
        
    


Aggiungere i seguenti valori al file colors.xml (aggiungere i valori-night solo se si utilizza il tema DayNight):

valori/colori.xml

#DE000000
#61000000
#8A000000
#1F000000
#1F000000
#8A000000
@android:color/white
#757575

values-night/colors.xml:

#1FFFFFFF
@android:color/white
#424242

3) L'ultima parte, far accadere la magia nel codice:

Impostare e inizializzare SearchView nell'attività desiderata

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

Alcune cose da notare sul codice:

1) L'animazione regolerà il suo punto di partenza in base al numero di voci di menu impostato e, se la barra degli strumenti ha un'icona di overflow, rileverà automaticamente se il layout è LTR o RTL.

2) Sto utilizzando l'attività navigation drawer, quindi ho impostato il colore della barra di stato su mDrawerLayout; se si utilizza un'attività regolare, è possibile impostare il colore della barra di stato in questo modo:

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

3) L'animazione di rivelazione circolare funziona solo su KitKat e versioni successive.

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

Passo - 1

Dichiarare una voce di menu


Passo - 2

Estendere AppCompatActivity e nel menu onCreateOptionsMenu impostare la 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;
    }

    ... 
}

L'idea è molto semplice: occorre scrivere la propria AutoCompleteTextView utilizzando EditText, TextWatcher e RecyclerView con l'adattatore Filterable.

  • EditText fornisce un campo di testo con la possibilità di inserire caratteri
  • TextWatcher consente di osservare le modifiche del testo
  • RecyclerView può essere posizionato ovunque, in modo da poter mostrare i risultati della ricerca proprio come nella vostra schermata
  • L'adattatore filtrabile aiuta a presentare i dati filtrati con il testo inserito

Quindi:

  • creare un layout con EditText in alto e RecyclerView che riempie lo spazio rimanente. Aggiungere l'icona, l'ombra, ecc.
  • aggiungere un TextWatcher e aggiornare l'adattatore a ogni modifica del testo

Se volete vedere la mia soluzione in azione, date un'occhiata al mio progetto su github:
https://github.com/ZieIony/Carbon

La demo completa di Auto può essere ascoltata nell'applicazione di esempio nella sezione 'Demo'.

Immagine dello schermo



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.