Coordinatorlayout Ignores Margins For Views With Anchor
Given I'm using a layout like this: Copy
Solution 2:
Try putting it in a linear layout that have padding:
<LinearLayoutwidth=".."height=".."paddingBottom="20dp"app:layout_anchor="@id/appbar"app:layout_anchorGravity="bottom|center_horizontal"><android.support.design.widget.FloatingActionButtonandroid:layout_width="70dp"android:layout_height="70dp"app:fabSize="normal" /></LinearLayout>
Solution 3:
As there might be bugs in the design-support-lib concerning the CoordinatorLayout
& margins, I wrote a FrameLayout
that implements/copies the same "Behavior" like the FAB and allows to set a padding
to simulate the effect:
Be sure to put it in the android.support.design.widget
package as it needs to access some package-scoped classes.
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import com.company.android.R;
import java.util.List;
@CoordinatorLayout.DefaultBehavior(FrameLayoutWithBehavior.Behavior.class)
publicclassFrameLayoutWithBehaviorextendsFrameLayout {
publicFrameLayoutWithBehavior(final Context context) {
super(context);
}
publicFrameLayoutWithBehavior(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
publicFrameLayoutWithBehavior(final Context context, final AttributeSet attrs, finalint defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)publicFrameLayoutWithBehavior(final Context context, final AttributeSet attrs, finalint defStyleAttr, finalint defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
publicstaticclassBehaviorextendsandroid.support.design.widget.CoordinatorLayout.Behavior<FrameLayoutWithBehavior> {
privatestaticfinalboolean SNACKBAR_BEHAVIOR_ENABLED;
private Rect mTmpRect;
privateboolean mIsAnimatingOut;
privatefloat mTranslationY;
publicBehavior() {
}
@OverridepublicbooleanlayoutDependsOn(CoordinatorLayout parent, FrameLayoutWithBehavior child, View dependency) {
return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout;
}
@OverridepublicbooleanonDependentViewChanged(CoordinatorLayout parent, FrameLayoutWithBehavior child, View dependency) {
if (dependency instanceof Snackbar.SnackbarLayout) {
this.updateFabTranslationForSnackbar(parent, child, dependency);
} elseif (dependency instanceof AppBarLayout) {
AppBarLayoutappBarLayout= (AppBarLayout) dependency;
if (this.mTmpRect == null) {
this.mTmpRect = newRect();
}
Rectrect=this.mTmpRect;
ViewGroupUtils.getDescendantRect(parent, dependency, rect);
if (rect.bottom <= appBarLayout.getMinimumHeightForVisibleOverlappingContent()) {
if (!this.mIsAnimatingOut && child.getVisibility() == VISIBLE) {
this.animateOut(child);
}
} elseif (child.getVisibility() != VISIBLE) {
this.animateIn(child);
}
}
returnfalse;
}
privatevoidupdateFabTranslationForSnackbar(CoordinatorLayout parent, FrameLayoutWithBehavior fab, View snackbar) {
floattranslationY=this.getFabTranslationYForSnackbar(parent, fab);
if (translationY != this.mTranslationY) {
ViewCompat.animate(fab)
.cancel();
if (Math.abs(translationY - this.mTranslationY) == (float) snackbar.getHeight()) {
ViewCompat.animate(fab)
.translationY(translationY)
.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
.setListener((ViewPropertyAnimatorListener) null);
} else {
ViewCompat.setTranslationY(fab, translationY);
}
this.mTranslationY = translationY;
}
}
privatefloatgetFabTranslationYForSnackbar(CoordinatorLayout parent, FrameLayoutWithBehavior fab) {
floatminOffset=0.0F;
Listdependencies= parent.getDependencies(fab);
inti=0;
for (intz= dependencies.size(); i < z; ++i) {
Viewview= (View) dependencies.get(i);
if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(fab, view)) {
minOffset = Math.min(minOffset, ViewCompat.getTranslationY(view) - (float) view.getHeight());
}
}
return minOffset;
}
privatevoidanimateIn(FrameLayoutWithBehavior button) {
button.setVisibility(View.VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
ViewCompat.animate(button)
.scaleX(1.0F)
.scaleY(1.0F)
.alpha(1.0F)
.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
.withLayer()
.setListener((ViewPropertyAnimatorListener) null)
.start();
} else {
Animationanim= android.view.animation.AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_in);
anim.setDuration(200L);
anim.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
button.startAnimation(anim);
}
}
privatevoidanimateOut(final FrameLayoutWithBehavior button) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
ViewCompat.animate(button)
.scaleX(0.0F)
.scaleY(0.0F)
.alpha(0.0F)
.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
.withLayer()
.setListener(newViewPropertyAnimatorListener() {
publicvoidonAnimationStart(View view) {
Behavior.this.mIsAnimatingOut = true;
}
publicvoidonAnimationCancel(View view) {
Behavior.this.mIsAnimatingOut = false;
}
publicvoidonAnimationEnd(View view) {
Behavior.this.mIsAnimatingOut = false;
view.setVisibility(View.GONE);
}
})
.start();
} else {
Animationanim= android.view.animation.AnimationUtils.loadAnimation(button.getContext(), R.anim.fab_out);
anim.setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR);
anim.setDuration(200L);
anim.setAnimationListener(newAnimationUtils.AnimationListenerAdapter() {
publicvoidonAnimationStart(Animation animation) {
Behavior.this.mIsAnimatingOut = true;
}
publicvoidonAnimationEnd(Animation animation) {
Behavior.this.mIsAnimatingOut = false;
button.setVisibility(View.GONE);
}
});
button.startAnimation(anim);
}
}
static {
SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
}
}
}
Solution 4:
Easy workaround is to anchor a random layout to where FAB was anchored, give it specific margin, and then anchor FAB to random layout, like this
<LinearLayout
android:orientation="horizontal"
android:id="@+id/fab_layout"
android:layout_width="5dp"
android:layout_height="5dp"
android:layout_marginRight="80dp"
android:layout_marginEnd="80dp"
app:layout_anchor="@id/collapsing_toolbar"
app:layout_anchorGravity="bottom|end"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_map"
app:layout_anchor="@id/fab_layout"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
Solution 5:
To anchor the FloatingActionButton
below the AppBar
like this:
Extend the FloatingActionButton
and override offsetTopAndBottom
:
publicclassOffsetFloatingActionButtonextendsFloatingActionButton
{
publicOffsetFloatingActionButton(Context context)
{
this(context, null);
}
publicOffsetFloatingActionButton(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
publicOffsetFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
@OverrideprotectedvoidonLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
ViewCompat.offsetTopAndBottom(this, 0);
}
@OverridepublicvoidoffsetTopAndBottom(int offset)
{
super.offsetTopAndBottom((int) (offset + (getHeight() * 0.5f)));
}
}
Post a Comment for "Coordinatorlayout Ignores Margins For Views With Anchor"