Clans / FloatingActionButton

Android Floating Action Button based on Material Design specification
Apache License 2.0
5.23k stars 1.13k forks source link

Support for CoordinatorLayout #61

Closed TomasValenta closed 8 years ago

TomasValenta commented 9 years ago

Hello again, it's possible to implement support for new CoordinatorLayout in this library? More discusion and explanation is on Stack Overflow.

lodlock commented 9 years ago

Until it's officially added it can be accomplished by creating a behavior. Here what I am currently using with my instance of FloatingActionMenu https://gist.github.com/lodlock/e3cd12130bad70a098db it can be easily modified to work with a FloatingActionButton as well.

Rainer-Lang commented 9 years ago

+1 @Clans When do you plan to release 1.6.0?

TomasValenta commented 9 years ago

Hello lodlock, I tried your gist but not working in my case. Can you help me please what is wrong?

I put your java class file to my project and I added the line to the FloatingActionMenu in xml:

    <com.github.clans.fab.FloatingActionMenu
        app:layout_behavior="cz.yetanotherview.webcamviewer.app.helper.FloatingActionMenuBehavior"
        android:id="@+id/floating_action_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="bottom|end"
        android:paddingRight="10dp"
        android:paddingBottom="8dp"
        android:paddingLeft="10dp"
        fab:menu_shadowColor="#37000000"
        fab:menu_colorNormal="#DA4336"
        fab:menu_colorPressed="#E75043"
        fab:menu_colorRipple="#99FFFFFF"
        fab:menu_icon="@drawable/fab_add"
        fab:menu_buttonSpacing="10dp"
        fab:menu_labels_textColor="@color/very_dark_grey"
        fab:menu_labels_textSize="14sp"
        fab:menu_labels_colorNormal="@color/white"
        fab:menu_labels_colorPressed="@color/next_grey"
        fab:menu_labels_colorRipple="#99FFFFFF"
        fab:menu_labels_margin="8dp"
        fab:menu_backgroundColor="@color/black_transparent">

that resides within a CoordinatorLayout and then I create the Snackbar:

        Snackbar.make(findViewById(R.id.coordinator_layout), R.string.dialog_positive_toast_message,
                Snackbar.LENGTH_SHORT).show();

but Snackbar overlaps FloatingActionMenu, like without your behavior. Any idea?

lodlock commented 9 years ago

Is your FloatingActionMenu inside of a CoordinatorLayout? If it is and you are still having issues you can extend the FloatingActionMenu itself and build the Behavior into it as an inner class. This way you wont need to include layout_behavior at all. This also fixes an issue where adding a layout_behavior sometimes causes Android Studio to not preview your layout anymore.

If that isn't an option for you you could do this dirty work around but it is not recommended. You can add an additional CoordinatorLayout wrapping only the FloatingActionMenu and use it for your Snackbar calls. It works but it's dirty.

TomasValenta commented 9 years ago

Yes, FloatingActionMenu is inside a CoordinatorLayout. Extending library is not for me and dirty solution not sounds so good ;) I can't understand why is not working your solution with app:layout_behavior in xml? You have an example with your implementation?

TomasValenta commented 9 years ago

So I made simple solution only until it's not officially added ;) https://github.com/TomasValenta/WebCamViewer/blob/master/app/src/main/java/cz/yetanotherview/webcamviewer/app/MainActivity.java#L1093

mmazzarolo commented 9 years ago

A small update to @lodlock 's solution for handling the Floating Action Menu hide/show on scroll. https://gist.github.com/mmazzarolo/7cf95a345bd8a59c0722

Clans commented 9 years ago

It looks like to implement this I'm gonna need to use a support design library as a dependency. I think it'll be inconvenient to have that inside a library module and in some cases - redundant. So I believe the best approach here is to use the custom Behavior that was provided in previous comments. Thanks guys for your contribution!

TomasValenta commented 9 years ago

Hello Matteo,

I tried also your solution, but only hide/show on scroll is working (FloatingActionMenu is inside of a CoordinatorLayout). Any idea why is not working also with Snackbars?

mmazzarolo commented 9 years ago

Hi @TomasValenta, can you provide a source of your CoordinatorLayout? Also, if you need an example, this fab is working correctly inside a CoordinatorLayout.

TomasValenta commented 9 years ago

Yes, here is. Thank you for your example, I will look at it ;)

Rainer-Lang commented 8 years ago

@mmazzarolo Doesn't work for me. layout_behaviour identifier not found.

knitterb-razzle commented 8 years ago

Make sure you're using the right attribute prefix of app:

<com.github.clans.fab.FloatingActionMenu
  ...
  app:layout_behavior="com.your.company.package.FloatingActionMenuBehavior"
  >
  ...
</com.github.clans.fab.FloatingActionMenu>

Working great for me!! Thanks!!!

baolongnt commented 8 years ago

I just pushed a PR #156 with 2 CoordinatorLayout.Behavior classes to support floating action button and menu. There is also some sample code in the PR.

Also, as the FloatingActionButton and FloatingActionMenu classes are annotated with @CoordinatorLayout.DefaultBehavior, you don't need to add the app:layout_behavior attribute in your XML layout anymore.

azizimusa commented 8 years ago

adding app:layout_behavior do nothing. In fact, it does not exist, I adding it manually.

<android.support.design.widget.CoordinatorLayout
                            android:id="@+id/main_content"
                            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="match_parent">

                        <ListView
                            android:id="@+id/listView"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"/>

                        <com.github.clans.fab.FloatingActionMenu
                            android:id="@+id/menu"
                            xmlns:fab="http://schemas.android.com/apk/res-auto"
                            app:layout_behavior="com.skoolfun.FloatingActionMenuBehavior"
                            android:layout_width="wrap_content"
                            android:layout_height="match_parent"
                            android:layout_marginLeft="10dp"
                            fab:menu_fab_size="normal"
                            fab:menu_showShadow="true"
                            fab:menu_shadowColor="#66000000"
                            fab:menu_shadowRadius="4dp"
                            fab:menu_shadowXOffset="1dp"
                            fab:menu_shadowYOffset="3dp"
                            fab:menu_colorNormal="#FFA200"
                            fab:menu_colorPressed="#413726"
                            fab:menu_colorRipple="#9c9890"
                            fab:menu_animationDelayPerItem="50"
                            fab:menu_icon="@drawable/fab_add"
                            fab:menu_buttonSpacing="0dp"
                            fab:menu_labels_margin="0dp"
                            fab:menu_labels_showAnimation="@anim/fab_slide_in_from_right"
                            fab:menu_labels_hideAnimation="@anim/fab_slide_out_to_right"
                            fab:menu_labels_paddingRight="8dp"
                            fab:menu_labels_paddingLeft="8dp"
                            fab:menu_labels_padding="8dp"
                            fab:menu_labels_textColor="#FFFFFF"
                            fab:menu_labels_textSize="14sp"
                            fab:menu_labels_cornerRadius="3dp"
                            fab:menu_labels_colorNormal="#333333"
                            fab:menu_labels_colorPressed="#444444"
                            fab:menu_labels_colorRipple="#66FFFFFF"
                            fab:menu_labels_showShadow="true"
                            fab:menu_labels_singleLine="false"
                            fab:menu_labels_ellipsize="none"
                            fab:menu_labels_maxLines="-1"
                            fab:menu_labels_position="right"
                            fab:menu_openDirection="up"
                            fab:menu_backgroundColor="@android:color/transparent"
                            android:layout_marginBottom="30dp">

                            <com.github.clans.fab.FloatingActionButton
                                android:id="@+id/fab_add"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:src="@drawable/fab_add"
                                fab:fab_colorNormal="#FFA200"
                                fab:fab_colorPressed="#c69440"
                                fab:fab_colorRipple="#7e6431"
                                fab:fab_size="normal"
                                fab:fab_label="Add New SmartTag Card" />

                            <com.github.clans.fab.FloatingActionButton
                                android:id="@+id/fab_activate"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:src="@drawable/ic_action_next_item"
                                fab:fab_colorNormal="#FFA200"
                                fab:fab_colorPressed="#c69440"
                                fab:fab_colorRipple="#7e6431"
                                fab:fab_size="normal"
                                fab:fab_label="Activate Additional SmartTag Card" />

                        </com.github.clans.fab.FloatingActionMenu>

                        </android.support.design.widget.CoordinatorLayout>

I can't make it to work. The FAB is still floating even scroll down.

xsorifc28 commented 8 years ago

@mmazzarolo I tried your behavior class but it is not working. I've defined the layout_behavior for the FloatingActionMenu inside a CoordinatorLayout. Any suggestions?

Using latest design support lib.

abramov73 commented 8 years ago

@xsorifc28 You need to add to behavior.

@Override
    public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {
        if (child instanceof FloatingActionMenu) {
            FloatingActionMenu fabMenu = (FloatingActionMenu) child;
            if (velocityY > 0) {
                fabMenu.hideMenuButton(true);
            } else if (velocityY < 0) {
                fabMenu.showMenuButton(true);
            }
        }
        return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
    }
AndreyNazarchuk commented 8 years ago

@abramov73 it says that it's not overriding the super class, and onNestedFling is undefined.

w3ggy commented 8 years ago

@AndreyNazarchuk u need to add this into this file: https://gist.github.com/mmazzarolo/7cf95a345bd8a59c0722 and set this behavior in xml file to the FAB: app:layout_behavior=".behaviors.FloatingActionMenuBehavior"

dawidhyzy commented 8 years ago

@w3ggy 404 :-/

mmazzarolo commented 8 years ago

@dawidhyzy here

robbyl commented 7 years ago

I tried to implement this behavior it works well on an emulator but weird results on a real device. The fab slides up out of sync with the snack bar and it does not slide back down when snack bar closes, both emulator and device run the same android version (Marshmallow)

Copy33 commented 7 years ago

Does anyone know how to anchor the FAM to a CollapsingToolbarLayout in a CoordinatorLayout?? I want it in a way where the main fab of the fam is anchored to the bottom edge of the collapsing toolbar...

hexlay commented 7 years ago

still facing problems with snackbar, is there any fix?

FelipeBerrios commented 7 years ago

When I use the FAM with a CollapsingToolbarLayout the button appears below the appbar. Any solution for this?

Niks345 commented 6 years ago

Not able to get it work as getting error Error:(52) No resource identifier found for attribute 'layout_behavoir' in package and here is my xml code

`<?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:layout_width="match_parent" android:layout_height="match_parent" xmlns:fab="http://schemas.android.com/apk/res-auto" android:background="@color/white">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_home" />

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<Button
    android:id="@+id/btn_book"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_gravity="top|center_horizontal"
    android:layout_marginBottom="20dp"
    android:background="@drawable/round_button"
    android:text="Unlock"
    android:textColor="@color/white"
    android:textSize="18sp"
    app:layout_anchor="@+id/map"
    app:layout_anchorGravity="bottom|center_horizontal" />

    <com.github.clans.fab.FloatingActionMenu
        android:id="@+id/fab_help"
        app:layout_behavoir="com.wowoni.bikesharing.bicyclesharing.Helper.FloatingActionMenuBehavior"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="10dp"
        android:layout_marginLeft="10dp"
        android:layout_gravity="bottom|end"
        fab:menu_fab_size="normal"
        fab:menu_showShadow="true"
        fab:menu_shadowColor="#66000000"
        fab:menu_shadowRadius="4dp"
        fab:menu_shadowXOffset="1dp"
        fab:menu_shadowYOffset="3dp"
        fab:menu_colorNormal="@color/white"
        fab:menu_colorPressed="@color/bg_main"
        fab:menu_colorRipple="#99FFFFFF"
        fab:menu_animationDelayPerItem="50"
        fab:menu_icon="@drawable/ic_iconmonstr_delivery_8"
        fab:menu_buttonSpacing="0dp"
        fab:menu_labels_margin="0dp"
        fab:menu_labels_showAnimation="@anim/fab_slide_in_from_right"
        fab:menu_labels_hideAnimation="@anim/fab_slide_out_to_right"
        fab:menu_labels_paddingTop="4dp"
        fab:menu_labels_paddingRight="8dp"
        fab:menu_labels_paddingBottom="4dp"
        fab:menu_labels_paddingLeft="8dp"
        fab:menu_labels_padding="8dp"
        fab:menu_labels_textColor="#FFFFFF"
        fab:menu_labels_textSize="14sp"
        fab:menu_labels_cornerRadius="3dp"
        fab:menu_labels_colorNormal="#333333"
        fab:menu_labels_colorPressed="#444444"
        fab:menu_labels_colorRipple="#66FFFFFF"
        fab:menu_labels_showShadow="true"
        fab:menu_labels_singleLine="false"
        fab:menu_labels_ellipsize="none"
        fab:menu_labels_maxLines="-1"
        fab:menu_labels_position="left"
        fab:menu_openDirection="up"
        fab:menu_backgroundColor="@android:color/transparent"
        fab:menu_fab_label=""
        fab:menu_fab_show_animation="@anim/show_from_bottom"
        fab:menu_fab_hide_animation="@anim/hide_to_bottom"
        >

        <com.github.clans.fab.FloatingActionButton
            android:id="@+id/help_illegal_parking"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            fab:fab_size="normal"
            fab:fab_label="Illegal Parking"
            android:src="@drawable/ic_iconmonstr_location_8"/>

        <com.github.clans.fab.FloatingActionButton
            android:id="@+id/help_unathorized_lock"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            fab:fab_size="normal"
            fab:fab_label="Unauthrized Lock"
            android:src="@drawable/ic_iconmonstr_lock_12"/>

        <com.github.clans.fab.FloatingActionButton
            android:id="@+id/help_broken_bike"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            fab:fab_size="normal"
            fab:fab_label="Broken Bike"
            android:src="@drawable/ic_iconmonstr_wrench_6"/>

    </com.github.clans.fab.FloatingActionMenu>

</android.support.design.widget.CoordinatorLayout> and Floatbutton behaviour code public class FloatingActionMenuBehavior extends CoordinatorLayout.Behavior { private float mTranslationY;

public FloatingActionMenuBehavior(Context context, int attrs) {
    super();
}

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    return dependency instanceof Snackbar.SnackbarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
    if ((child instanceof FloatingActionMenu || child instanceof FloatingActionButton)
            && dependency instanceof Snackbar.SnackbarLayout) {
        this.updateTranslation(parent, child, dependency);
    }

    return false;
}

@Override
public void onDependentViewRemoved(CoordinatorLayout parent, View child, View dependency) {
    if ((child instanceof FloatingActionMenu || child instanceof FloatingActionButton)
            && dependency instanceof Snackbar.SnackbarLayout) {
        this.updateTranslation(parent, child, dependency);
    }
}

private void updateTranslation(CoordinatorLayout parent, View child, View dependency) {
    float translationY = this.getTranslationY(parent, child);
    if (translationY != this.mTranslationY) {
        ViewCompat.animate(child)
                .cancel();
        if (Math.abs(translationY - this.mTranslationY) == (float) dependency.getHeight()) {
            ViewCompat.animate(child)
                    .translationY(translationY)
                    .setListener((ViewPropertyAnimatorListener) null);
        } else {
            ViewCompat.setTranslationY(child, translationY);
        }

        this.mTranslationY = translationY;
    }

}

@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {
    if (child instanceof FloatingActionMenu) {
        FloatingActionMenu fabMenu = (FloatingActionMenu) child;
        if (velocityY > 0) {
            fabMenu.hideMenuButton(true);
        } else if (velocityY < 0) {
            fabMenu.showMenuButton(true);
        }
    }
    return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}

private float getTranslationY(CoordinatorLayout parent, View child) {
    float minOffset = 0.0F;
    List dependencies = parent.getDependencies(child);
    int i = 0;

    for (int z = dependencies.size(); i < z; ++i) {
        View view = (View) dependencies.get(i);
        if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(child, view)) {
            minOffset = Math.min(minOffset, ViewCompat.getTranslationY(view) - (float) view.getHeight());
        }
    }

    return minOffset;
}

}`

and main activity implementation CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) help.getLayoutParams(); params.setBehavior(new FloatingActionMenuBehavior(this,R.style.Floating_button)); help.requestLayout();