J'ai mis à jour mon Android application) avec le nouveau design de matériau, mais je souhaitais également ajouter une ombre ou une élévation à la barre d'outils. -patches, mais je me demande si cela peut être fait via les bibliothèques de support (tout comme le CardView
peut avoir une élévation)
Selon la réponse de this à une autre question, cela est possible en enveloppant le Toolbar
dans un AppBarLayout
, mais cela ne fonctionne pas pour moi.
Ma mise en page:
<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.AppBarLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
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="wrap_content"
Android:minHeight="?attr/actionBarSize"
Android:background="?attr/colorPrimary"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</Android.support.design.widget.AppBarLayout>
J'ai également essayé de définir l'altitude via XML et via le code, mais cela ne fonctionne pas non plus.
Toute aide serait appréciée! Merci d'avance.
Mise à jour:
Puisque j'inclus ma mise en forme dans la barre d'outils dans mes autres mises en page, voici l'une de mes mises en page principales:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<include
layout="@layout/Toolbar" />
<fragment
class="OverAllField.XamarinAndroid.Fragments.Planning.PlanningFragment"
Android:id="@+id/PlanningFragment"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1" />
</LinearLayout>
Pour Android 5.0 et supérieur: AppBarLayout fournit/donne automatiquement des ombres dans la présentation. Vous pouvez également augmenter l’altitude de AppBarLayout de app:elevation="4dp"
.
Pour les pré-sucettes: Vous pouvez utiliser le lien suivant: https://github.com/vipulasri/Toolbar-Elevation-Pre-Lollipop
Remarque: La barre d’outils prend également en charge l’élévation, en utilisant Android:elevation="4dp"
Nouvelle mise à jour: Dans Appcompat v24.0.0, vous ne pouvez pas définir l'élévation sur AppBarLayout à l'aide de setElevation()
et app:elevation
car ils sont obsolètes.
Vous devez utiliser la propriété stateListAnimator
pour définir l'altitude maintenant.
Remarque: définissez la durée sur 1 ms dans StateListAnimator
afin de éviter les retards dans le dessin en élévation.
Le changement d'élévation AppBarLayout est retardé sur appCompat v24.0.
appbar_always_elevated.xml dans animator-v21 dossier sous = res répertoire.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item>
<objectAnimator Android:propertyName="elevation"
Android:valueTo="8dp"
Android:valueType="floatType"
Android:duration="1"/>
</item>
</selector>
Dans AppbarLayout:
<Android.support.design.widget.AppBarLayout
Android:layout_width="match_parent"
Android:layout_height="300dp"
Android:fitsSystemWindows="true"
Android:stateListAnimator="@animator/appbar_always_elevated"
Android:theme="@style/AppTheme.AppBarOverlay">
</Android.support.design.widget.AppBarLayout>
Essayez d'utiliser AppBarLayout dans la présentation de l'activité. Essayer:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="match_parent"
Android:layout_height="match_parent">
<Android.support.design.widget.AppBarLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<include
layout="@layout/Toolbar" />
</Android.support.design.widget.AppBarLayout>
<fragment
class="OverAllField.XamarinAndroid.Fragments.Planning.PlanningFragment"
Android:id="@+id/PlanningFragment"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1" />
</LinearLayout>
Toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
Android:minHeight="?attr/actionBarSize"
Android:background="?attr/colorPrimary"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
utiliser le fichier de construction:
compile 'com.Android.support:cardview-v7:23.1.1'
appeler en xml ajouter:
app:cardElevation="8dp"
app:cardCornerRadius="8dp"
app:contentPadding="5dp"
J'ai un CollapsingToolbarLayout
avec Toolbar
et une barre semblable à une barre d'outils View
qui monte et descend, mais se situe au-dessus de NestedScrollView
, comme dans https : //github.com/k0shk0sh/CoordinatorLayoutExample . J'ai essayé beaucoup de variantes. Parfois, une ombre défilait au-dessus d'un écran avec NestedScrollView, parfois la barre d'outils dessinait une ombre pleine sans transparence, parfois l'ombre était aliasée. Quoi qu'il en soit, c'est ma solution.
Dis, tu as une mise en page:
<Android.support.design.widget.CoordinatorLayout>
<Android.support.design.widget.AppBarLayout>
<Android.support.design.widget.CollapsingToolbarLayout>
<Android.support.v7.widget.Toolbar>
<!-- Toolbar views if needed -->
</Android.support.v7.widget.Toolbar>
</Android.support.design.widget.CollapsingToolbarLayout>
</Android.support.design.widget.AppBarLayout>
<!-- Footer Toolbar views if needed -->
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout>
<!-- Views -->
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
<!-- Add this view. It draws a shadow and aligns top of NestedScrollView -->
<!-- Set visibility to gone or visible -->
<View
Android:id="@+id/scroll_shadow"
Android:layout_width="match_parent"
Android:layout_height="4dp"
Android:background="@drawable/shadow"
Android:visibility="gone"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</Android.support.design.widget.CoordinatorLayout>
Ajoutez une ombre ( drawable/shadow.xml ):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
<gradient
Android:angle="90"
Android:endColor="#ffcccccc"
Android:startColor="#00cccccc" />
</shape>
Ajoutez cette méthode. ScrollShadow est une vue nommée "scroll_shadow":
private void setShadowVisibility(int visibility) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
scrollShadow.setVisibility(visibility);
}
}
Manipulez-le comme vous le souhaitez. Il montrera un dégradé sur les appareils pré-Lollipop et montrera une ombre normale pour Android 5.0+.
Je pense que la meilleure solution est de placer une vue ombrée en dégradé sous la barre d’outils et de manipuler avec une visibilité qui dépend du périphérique sdk.
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<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"
Android:background="@Android:color/white"
Android:fitsSystemWindows="true"
app:popupTheme="@style/AppTheme.PopupOverlay">
<TextView
Android:id="@+id/centerTitleToolbarTextView"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:gravity="center"
Android:maxLines="1"
Android:textColor="@color/color_toolbar"
Android:textSize="@dimen/titleToolbar" />
</Android.support.v7.widget.Toolbar>
<View
Android:id="@+id/shadow_view"
Android:layout_width="match_parent"
Android:visibility="gone"
Android:layout_height="4dp"
Android:background="@drawable/toolbar_shadow" />
</LinearLayout>
toolbar_shadow.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android">
<gradient
Android:startColor="#c1c1c1"
Android:centerColor="#e6e6e6"
Android:endColor="#f1f1f1"
Android:angle="270" />
</shape>
MainActivity.class
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
findViewById(R.id.shadow_view).setVisibility(View.VISIBLE);
}
J'ai également perdu un jour sur cette question, mais j'ai finalement trouvé un moyen de le faire fonctionner.
/**
* Controller for the toolbar which will take care of the drop down shadow also on pre-Lollipop devices.
* <br/>
* The controller also handles the status bar based on the state of the toolbar.
* <p/>
* Created by <b>Negru Ionut Valentin</b> on <b>20/1/2016</b>.
*/
public class ToolbarController {
private boolean handleStatusBar = false;
private boolean showTitle = true;
/**
* Call this method in onCreate() method of your Activity or in onCreateView() in Fragment
*
* @param view
* The view into which to look for the toolbar
* @param activity
* The activity for which setup the toolbar
*
* @return The toolbar found and customized or {@code null}
*/
public Toolbar initToolbar(View view, Activity activity) {
Toolbar mToolbar = (Toolbar) view.findViewById(R.id.toolbar);
// Valid and visible toolbar - otherwise ignore
if (null != mToolbar && mToolbar.getVisibility() == View.VISIBLE) {
int paddingLeft = mToolbar.getPaddingLeft();
int paddingRight = mToolbar.getPaddingRight();
int paddingBottom = mToolbar.getPaddingBottom();
// Set the top padding of the toolbar to match the status bar height
int paddingTop = new CynnyContextWrapper(activity).getStatusBarHeight();
mToolbar.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Lollipop) {
ViewParent parent = mToolbar.getParent();
if (parent instanceof RelativeLayout) {
// Manually create the drop shadow
RelativeLayout.LayoutParams params =
new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
Metrics.convertDpToPixel(4, activity));
View dropShadow = new View(activity);
dropShadow.setBackgroundResource(R.drawable.toolbar_shadow);
params.addRule(RelativeLayout.BELOW, R.id.toolbar);
((RelativeLayout) parent).addView(dropShadow, params);
}
}
if (activity instanceof AppCompatActivity) {
// Check if the Activity actually support ActionBar with Toolbar and set our custom Toolbar for it
((AppCompatActivity) activity).setSupportActionBar(mToolbar);
// Get the actionbar from the activity
ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
if (null != actionBar) {
// If the actionbar is valid, customize it
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayShowTitleEnabled(this.showTitle);
mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_selector);
}
}
if (this.handleStatusBar) {
// For showing the status bar
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
}
} else if (handleStatusBar) {
// Force hide the status bar
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
}
return mToolbar;
}
/**
* Set the flag indicating if the controller should handle or not the status bar.
*
* @param handleStatusBar
* Flag which indicates if the initialization of the toolbar should also update
* the status bar state (if two calls are made for the init, the last one will
* be taken into consideration).
*
* @return The current toolbar controller.
*/
public ToolbarController setHandleStatusBar(boolean handleStatusBar) {
this.handleStatusBar = handleStatusBar;
return this;
}
/**
* Set the flag indicating if the toolbar should show or hide the title.
*
* @param showTitle
* Flag indicating if the toolbar should also show the title (the title can be changed after the toolbar
* initialization)
*
* @return The current toolbar controller.
*/
public ToolbarController setShowTitle(boolean showTitle) {
this.showTitle = showTitle;
return this;
}
}
Dans l'activité, vous devriez utiliser ceci dans la méthode onCreate () comme ceci:
// Create and customize the Toolbar controller
new ToolbarController().setHandleStatusBar(true).setShowTitle(true)
.initToolbar(((ViewGroup) findViewById(Android.R.id.content)).getChildAt(0),
this);
Dans le fragment, vous devriez utiliser ceci dans la méthode onCreateView () comme ceci:
new ToolbarController().setHandleStatusBar(false).setShowTitle(false).initToolbar(resultView, getActivity());
N'oubliez pas d'ajouter votre barre d'outils dans les mises en page et de définir son identifiant avec Android:id="@id/toolbar"
. Si vous souhaitez utiliser un autre identifiant, vous pouvez personnaliser le contrôleur et ajouter une autre méthode de définition utilisant l'identifiant fourni.
J'ai deux configurations de barre d'outils créées:
v21
<!-- This is the new widget added in Lollipop - use with care -->
<Android.support.v7.widget.Toolbar
Android:id="@id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:minHeight="?attr/actionBarSize"
Android:theme="@style/TitleToolbarTheme"
Android:background="?android:attr/colorPrimary"
Android:elevation="@dimen/toolbar_elevation"
/>
</merge>
autre
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:Android="http://schemas.Android.com/apk/res/Android"
>
<!-- This is the new widget added in Lollipop - use with care -->
<Android.support.v7.widget.Toolbar
Android:id="@id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:minHeight="?attr/actionBarSize"
Android:theme="@style/TitleToolbarTheme"
Android:background="?attr/colorPrimary"
/>
</merge>
Je les utilise dans les mises en page de mai en utilisant:
<include layout="@layout/toolbar" />
J'espère que cela aidera à résoudre votre problème. Notez également que cela peut être optimisé davantage, mais cela fonctionne pour moi et je ne veux plus perdre de temps sur ce sujet.