Ich versuche, meine FloatingActionButton fabLocation
programmgesteuert zu verbergen mit:
fabLocation.setVisibility(View.GONE)
aber es funktioniert nicht.
Wenn ich Android:visibility="gone"
in meinem XML-Layout hinzufüge, wird fabLocation
beim Ausführen meiner Aktivität ausgeblendet, aber beim Scrollen wieder angezeigt.
Hier ist mein Layout:
<?xml version="1.0" encoding="utf-8"?>
<Android.support.design.widget.CoordinatorLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/main_content"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true">
<Android.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:fitsSystemWindows="true"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<Android.support.design.widget.CollapsingToolbarLayout
Android:id="@+id/collapsing_toolbar"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
app:contentScrim="@color/colorOverlay"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
Android:id="@+id/img_couverture"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true"
Android:scaleType="centerCrop"
Android:src="@drawable/bg_navigation_drawer_header"
app:layout_collapseMode="parallax" />
<Android.support.v7.widget.Toolbar
Android:id="@+id/toolbar"
Android:layout_width="match_parent"
Android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</Android.support.design.widget.CollapsingToolbarLayout>
</Android.support.design.widget.AppBarLayout>
<Android.support.v4.widget.NestedScrollView
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical">
<Android.support.v7.widget.CardView
Android:layout_marginTop="8dp"
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<LinearLayout
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:orientation="vertical"
Android:padding="16dp">
<TextView
Android:id="@+id/tv_name"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:textSize="18sp" />
<View
Android:background="@drawable/separator_orange_gradient"
Android:layout_marginTop="8dp"
Android:layout_marginBottom="16dp"
Android:layout_width="match_parent"
Android:layout_height="2dp"/>
<TextView
Android:id="@+id/tv_history"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:textAppearance="@style/TextAppearance.RobotoLight" />
</LinearLayout>
</Android.support.v7.widget.CardView>
</LinearLayout>
</Android.support.v4.widget.NestedScrollView>
<Android.support.design.widget.FloatingActionButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_margin="16dp"
Android:clickable="true"
Android:id="@+id/fab_location"
Android:src="@drawable/ic_fab_location_24dp"
app:backgroundTint="@color/colorOrange"
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end" />
Dies ist auf das app:layout_anchor
-Attribut zurückzuführen. Sie müssen den Anker entfernen, bevor Sie die Sichtbarkeit ändern:
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.setVisibility(View.GONE);
In AppBarLayouts verankerte FloatingActionButtons haben eine besondere Beziehung, deren Sichtbarkeit durch die Bildlaufposition des AppBarLayout gesteuert wird.
Sie können dies über das behavior_autoHide
-Attribut deaktivieren:
<Android.support.design.widget.FloatingActionButton
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
app:layout_anchor="..."
app:behavior_autoHide="false"/>
Sie können dies auch programmgesteuert ausführen, wenn Sie möchten:
FloatingActionButton.Behavior b
= (FloatingActionButton.Behavior) fab.getBehavior();
b.setAutoHideEnabled(false);
Die einfachste Möglichkeit, eine schwebende Aktionsleiste auszublenden und anzuzeigen, besteht darin, dies in Ihrer Aktivität aufzurufen.
Verbergen, verstecken:
nameOfYourFAB.Hide();
Show:
nameOfYourFAB.Show();
Wenn Sie ausgeblendete FAB anzeigen möchten
<Android.support.design.widget.CoordinatorLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:id="@+id/coordinator"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:fitsSystemWindows="true">
<Android.support.design.widget.AppBarLayout
Android:id="@+id/appbar"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
Android:fitsSystemWindows="true">
...
</Android.support.design.widget.AppBarLayout>
...
<Android.support.design.widget.FloatingActionButton
Android:id="@+id/fab"
Android:visibility="gone"
Android:layout_height="wrap_content"
Android:layout_width="wrap_content"
Android:clickable="true"/>
</Android.support.design.widget.CoordinatorLayout>
und
CoordinatorLayout.LayoutParams p = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.WRAP_CONTENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT);
p.anchorGravity = Gravity.BOTTOM | Gravity.END;
p.setAnchorId(R.id.appbar);
p.setMargins(...);
fab.setLayoutParams(p);
fab.setVisibility(View.VISIBLE);
Ich war mit keiner der veröffentlichten Lösungen völlig zufrieden. Einige haben nur zeitweise gearbeitet, während andere nur für fab.setVisibility()
gearbeitet haben. Ich weiß zwar, dass dies die ursprüngliche Frage ist, die die ursprüngliche Frage stellte, aber ein paar Antworten äußerten Interesse an der Verwendung von fab.hide()
, und das Durcheinanderbringen der Layout-Parameter ist nicht genau an der Wurzel des Problems.
Wie @ChrisBanes darauf hinweist, ist der FloatingActionButton.Behavior
, der an die AppBarLayout
gebunden ist, das Problem. Wie bei seiner Antwort müssen Sie setAutoHideEnabled(false)
deaktivieren, um diese Funktion zu deaktivieren. Diese Lösung ist jedoch nicht hilfreich, wenn die FloatingActionButton
tatsächlich automatisch und ausblenden soll, wenn Sie hide()
manuell aufrufen.
Also, um dies zu tun; Ich deaktiviere einfach die Funktion zum automatischen Ausblenden, bevor ich die Variable Button
manuell verstecke, und schalte die Funktionalität wieder ein, nachdem ich die Variable Button
manuell angezeigt habe:
private void hideFloatingActionButton(FloatingActionButton fab) {
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) fab.getLayoutParams();
FloatingActionButton.Behavior behavior =
(FloatingActionButton.Behavior) params.getBehavior();
if (behavior != null) {
behavior.setAutoHideEnabled(false);
}
fab.hide();
}
private void showFloatingActionButton(FloatingActionButton fab) {
fab.show();
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) fab.getLayoutParams();
FloatingActionButton.Behavior behavior =
(FloatingActionButton.Behavior) params.getBehavior();
if (behavior != null) {
behavior.setAutoHideEnabled(true);
}
}
FloatingActionButton layers = (FloatingActionButton) findViewById(R.id.layers);
layers.hide();
Es funktioniert für mich, setVisibility
funktioniert nicht für FloatingActionButton
, da es zu einer anderen viewGroup
gehört, die keine setVisibility
-Methode hat.
Nach einigen Antworten fand ich die Lösung für mein Problem (auch wenn die Fabrik versteckt ist, kann sie mit Action umgehen!).
Als Erstes schlage ich vor, dass Sie .setVisibility(View.GONE)
und .setVisibility(View.VISIBLE)
durch die Methoden .show()
und .hide()
ersetzen. Diese letzten Handle auch actionMode
.
Das zweite Problem für mich war die Aktion, die auch ausgeführt wurde, als die Fabrik versteckt wurde. Um dies zu beheben, habe ich es geschafft:
final CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams)floatingActionButton.getLayoutParams();
if (show){
p.setAnchorId(R.id.appBarLayout);
p.width = CoordinatorLayout.LayoutParams.WRAP_CONTENT;
p.height = CoordinatorLayout.LayoutParams.WRAP_CONTENT;
floatingActionButton.setLayoutParams(p);
floatingActionButton.show();
}else{
p.setAnchorId(View.NO_ID);
p.width = 0;
p.height = 0;
floatingActionButton.setLayoutParams(p);
floatingActionButton.hide();
}
So verbergen Sie die schwebende Schaltfläche
fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.hide;
und wieder zu zeigen
fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
fab.show;
Die eigentliche Lösung für Ihr Problem ist die Unterklasse default FloatingActionButton.Behavior
, um setAutoHide(false)
in ihren Konstruktoren aufzurufen, damit Sie es selbst steuern können.
Beachten Sie, dass ich unten über die unteren Blätter spreche, aber es ist genau das gleiche Problem für alle verankerten schwebenden Aktionsschaltflächen. Es beantwortet die Frage und sollte das Problem wie erwartet lösen.
Alternativ können Sie die boolean onDependentViewChanged(…)
-Methode in Ihrem benutzerdefinierten Verhalten überschreiben, die statische isBottomSheet(…)
-Methode in der FloatingActionButton.Behavior
-Klasse kopieren und den Wert der übergeordneten Methode nur aufrufen und zurückgeben, wenn es sich nicht um ein unteres Blatt handelt.
Sie können das Standardverhalten auf diese Weise weiter anpassen oder die Vanilla CoordinatorLayout.Behavior
-Klasse direkt erweitern, und Sie können den Pickcode auswählen, um das Einfügen aus der FloatingActionButton.Behavior
-Klasse bei Bedarf zu kopieren.
Hier ist der Code, den ich verwendet habe, um die Sichtbarkeit der FAB zu kontrollieren:
/**
* Allows controlling the FAB visibility manually.
*/
@SuppressWarnings("unused")
public class FabManualHideBehavior extends FloatingActionButton.Behavior {
public FabManualHideBehavior() {
super();
setAutoHideEnabled(false);
}
public FabManualHideBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
setAutoHideEnabled(false);
}
}
Und ich habe es in xml auf meine FAB angewendet:
<Android.support.design.widget.CoordinatorLayout
...>
...
<Android.support.design.widget.FloatingActionButton
...
app:layout_anchor="@+id/bottom_sheet"
app:layout_anchorGravity="top|end"
app:layout_behavior="your.package.name.ui.behavior.FabManualHideBehavior"/>
</Android.support.design.widget.CoordinatorLayout>
Keine dieser anderen Lösungen hat mir zu 100% geholfen. Ich musste wiederholt animiert anzeigen und verbergen (wie FAB.show()
und hide()
), während ich in der App-Leiste verankert war, wenn sie sichtbar war.
Ich habe das FAB jedes Mal neu erstellt, wenn ich es zeigte, manuell einfügte und verankerte und es basierend auf der Implementierung der Unterstützungsbibliothek animierte. Es ist grob, aber es funktioniert perfekt.
private void hidePlayButton(final FloatingActionButton fab) {
// Cancel any animation from the default behavior
fab.animate().cancel();
fab.animate()
.scaleX(0f)
.scaleY(0f)
.alpha(0f)
.setDuration(200)
.setInterpolator(new FastOutLinearInInterpolator())
.setListener(new Animator.AnimatorListener() {
@Override public void onAnimationStart(Animator animation) {}
@Override public void onAnimationEnd(Animator animation) {
coordinatorLayout.removeView(fab);
}
@Override public void onAnimationCancel(Animator animation) {}
@Override public void onAnimationRepeat(Animator animation) {}
});
}
private void showPlayButton() {
int fabSize = getResources().getDimensionPixelSize(R.dimen.fab_size);
int margin = getResources().getDimensionPixelSize(R.dimen.fab_margin);
final FloatingActionButton fab = new FloatingActionButton(getActivity());
fab.setBackgroundTintList(ColorStateList.valueOf(ContextCompat.getColor(getActivity(), R.color.tint)));
fab.setImageDrawable(ContextCompat.getDrawable(getActivity(), R.drawable.play));
CoordinatorLayout.LayoutParams p = new CoordinatorLayout.LayoutParams(fabSize, fabSize);
p.rightMargin = p.leftMargin = p.bottomMargin = p.topMargin = margin;
p.anchorGravity = Gravity.BOTTOM | Gravity.END;
p.setAnchorId(R.id.appbar);
fab.setLayoutParams(p);
// Start from 1 pixel
fab.setAlpha(0f);
fab.setScaleX(0f);
fab.setScaleY(0f);
binding.coordinatorLayout.addView(fab);
fab.animate()
.alpha(1f)
.scaleX(1f)
.scaleY(1f)
.setDuration(200)
.setInterpolator(new FastOutLinearInInterpolator());
fab.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
hidePlayButton(fab);
// do action
}
});
}
Ich benutze diesen Code:
boolean mFabShouldBeShown;
FloatingActionButton.OnVisibilityChangedListener fabListener = new FloatingActionButton.OnVisibilityChangedListener() {
@Override
public void onShown(FloatingActionButton fab) {
super.onShown(fab);
if(!mFabShouldBeShown){
fab.hide();
}
}
@Override
public void onHidden(FloatingActionButton fab) {
super.onHidden(fab);
if(mFabShouldBeShown){
fab.show();
}
}
};
public void methodWhereFabIsHidden() {
mFabShouldBeShown = false;
mFloatingActionButton.hide(fabListener);
}
public void methodWhereFabIsShown() {
mFabShouldBeShown = true;
mFloatingActionButton.show(fabListener);
}
Wenn Sie die Fab ausblenden möchten, können Sie Folgendes versuchen: Fab.hide ();
sonst versuchen fab.show ();
genießen.
Ich habe den Mangel in show ()/hide () umgangen, indem ich die FAB mithilfe von Layouträndern auf dem Bildschirm oder außerhalb des Bildschirms platzierte. Beispiel:
CoordinatorLayout.LayoutParams p =
new CoordinatorLayout.LayoutParams(
CoordinatorLayout.LayoutParams.WRAP_CONTENT,
CoordinatorLayout.LayoutParams.WRAP_CONTENT);
p.gravity = Gravity.BOTTOM | Gravity.LEFT;
int fabMargin = (int)res.getDimension(R.dimen.fab_margin);
if( enabled ) {
p.setMargins(fabMargin,0,0,fabMargin);
}
else {
p.setMargins(-200,0,0,fabMargin);
}
mFab.setLayoutParams(p);
Einfacher Code:
public static void setVisibilityFab(FloatingActionButton fab, int visibility)
{
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setAnchorId(View.NO_ID);
fab.setLayoutParams(p);
if(visibility==View.GONE || visibility==View.INVISIBLE)
fab.setVisibility(View.GONE);
else
fab.setVisibility(View.VISIBLE);
}
Ich weiß, dass es sich bei Ihrer Antwort um die Frage handelt, wie sie für die gone
-Sichtbarkeit funktionieren soll. Wenn Sie jedoch stattdessen invisible
verwenden, müssen Sie sich keine Sorgen machen und haben weniger Code.
hier ist eine einfache Lösung
private var fabAnchorId: Int = View.NO_ID
private val fabParams: CoordinatorLayout.LayoutParams
get() = (fab.layoutParams as CoordinatorLayout.LayoutParams)
fun showFab() {
fabParams.anchorId = fabAnchorId
fabParams.gravity = Gravity.NO_GRAVITY
fab.show()
}
fun hideFab() {
fabParams.anchorId = View.NO_ID
fabParams.gravity = Gravity.END.or(Gravity.BOTTOM)
fab.hide()
}
vor dem Zeigen/Verstecken müssen wir Anker und Schwerkraft wechseln