J'ai cherché des moyens d'implémenter une searchview dans la barre d'outils d'activité (actionbar) conformément au directives de conception de matériel.
En cliquant sur l'icône de recherche, la barre d'outils entière s'anime pour que seul le texte de recherche EditText avec un arrière-plan blanc avec des suggestions apparaissant dans la vue principale au lieu d'un menu déroulant.
Voici une capture d'écran des lignes directrices:
Voici un gif de l'implémentation de la boîte de réception Gmail:
Je cherchais des exemples de code et des tutoriels, mais jusqu'à présent, j'ai été infructueux. Comment puis-je faire cela?
J'ai essayé plusieurs bibliothèques SearchView matérielles, mais aucune d'entre elles ne fonctionnait bien, mais j'ai décidé de la redéfinir. Après beaucoup de travail, je suis ravie du résultat:
Voici comment vous pouvez le faire:
1) Ajouter un élément SearchView à votre menu
<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" />
Notez que je déclare actionLayout au lieu de actionViewClass , j'ai pensé que c'est le seul moyen de définir le thème SearchView séparément du thème de la barre d'outils.
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) Ajoutez le thème SearchView personnalisé à vos styles, déclarez également le thème SearchView dans votre thème de barre d’outils:
<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>
Notez que j'ai ajouté une vue déroulante ancre sous la vue Barre d'outils, de sorte que les suggestions obtiennent une largeur d'écran complète.
<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:
(modifiez la visibilité de suggestion_divider si vous souhaitez séparer les suggestions):
<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" />
Le fond des suggestions et l'icône de validation sont personnalisés, le reste des icônes que j'ai utilisées se trouvent à l'adresse suivante: 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>
Ajoutez les valeurs suivantes à votre fichier colors.xml (ajoutez les valeurs nuit uniquement si vous utilisez le thème DayNight):
valeurs/couleurs.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>
valeurs-nuit/couleurs.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) Dernière partie, créez la magie dans le code:
Configurez et initialisez SearchView dans l'activité de votre choix
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;
}
Peu de choses à noter sur le code:
1) L’animation ajustera son point de départ en fonction de votre ensemble d’éléments de menu. Si la barre d’outils contient une icône de débordement, elle détectera automatiquement si la mise en page est LTR ou RTL.
2) J'utilise l'activité du tiroir de navigation. J'ai donc défini la couleur de StatusBar sur mDrawerLayout. Si vous utilisez une activité normale, vous pouvez définir la couleur de StatusBar de la manière suivante:
getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.quantum_grey_600));
3) L’animation de révélation circulaire ne fonctionnera que sur KitKat et au-dessus.
En fait, il est très facile de le faire si vous utilisez la bibliothèque Android.support.v7.
étape - 1
Déclarer un élément de 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" />
étape - 2
Étendez AppCompatActivity et dans le onCreateOptionsMenu, configurez 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'idée est très simple: vous devez écrire votre propre AutoCompleteTextView à l'aide d'EditText, TextWatcher et RecyclerView avec un adaptateur filtrable.
Alors:
Si vous souhaitez voir ma solution en action, consultez mon projet sur github: https://github.com/ZieIony/Carbon
La démo de finalisation automatique peut être sonore dans l'exemple d'application dans la section 'Démos'.
Prenant un indice de la réponse de @ Zielony, j’ai fait ce qui suit:
1) À la place, si vous utilisez une barre d’action ou une barre d’outils, j’ai construit ma propre mise en page (essentiellement un menu RelativeLayout avec hamburger, des boutons de recherche et d’autres menus et un texte EditText pour la recherche)
2) A utilisé un thème sans barre d’action, a placé ma présentation personnalisée en haut de l’activité de sorte qu’elle apparaisse comme une barre d’action.
3) Dans le bouton de recherche OnClickListener, je fais 2 choses:
3) OnClickListeners ajouté pour les autres boutons de menu.
4) Ajout d'un TextWatcher sur le champ 'search' EditText pour afficher les astuces de recherche et les résultats du serveur.
Voici comment cela apparaît maintenant:
Voici comment j'ai essayé de le mettre en œuvre, veuillez vérifier ceci.
Je pense que je l'ai compris. J'utilise maintenant seulement un EditText à l'intérieur de la barre d'outils.
J'ai maintenant ceci:
Tout d'abord dans onCreate () de mon activité, j'ai ajouté le EditText avec une vue d'image sur le côté droit de la barre d'outils comme ceci:
// 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);
Cela a fonctionné, mais j'ai rencontré un problème où onOptionsItemSelected () n'était pas appelé lorsque j'ai appuyé sur le bouton d'accueil. Je n'ai donc pas pu annuler la recherche en appuyant sur le bouton d'accueil. J'ai essayé différentes méthodes pour enregistrer l'auditeur de clics sur le bouton d'accueil, mais cela n'a pas fonctionné.
Finalement, j'ai découvert que le ActionBarDrawerToggle que j'avais interférait avec des choses, alors je l'ai supprimé. Cet écouteur a alors commencé à fonctionner:
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));
}
});
Donc, je peux maintenant annuler la recherche avec le bouton d'accueil, mais je ne peux pas appuyer sur le bouton de retour pour l'annuler pour le moment. J'ai donc ajouté ceci à 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;
}
}
J'ai créé cette méthode pour activer la visibilité de l'élément EditText et du 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);
}
}
J'avais besoin d'un moyen de basculer le bouton d'accueil de la barre d'outils entre l'icône du tiroir et le bouton précédent. J'ai finalement trouvé la méthode ci-dessous dans cette réponse SO. Même si je l'ai légèrement modifiée, cela a plus de sens pour moi:
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);
}
}
}
Cela fonctionne, j'ai réussi à résoudre quelques bugs que j'ai trouvés en chemin. Je ne pense pas que ce soit à 100% mais cela fonctionne assez bien pour moi. EDIT: Si vous souhaitez ajouter la vue de recherche en XML au lieu de Java procédez comme suit:
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 () de votre activité:
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);
Vous pouvez utiliser AutoCompleteTextView pour y parvenir, suivez le lien ci-dessous
Comment construire Gmail comme un champ de recherche dans la barre d’actions?