I can't hide my FloatingActionButton. Here is my code:
XML:
<CoordinatorLayout>
<AppBarLayout android:id="#+id/appbar">
<CollapsingToolbarLayout>
<ImageView/>
<android.support.v7.widget.Toolbar />
</CollapsingToolbarLayout>
</AppBarLayout>
<NestedScrollView />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
app:layout_anchor="#id/appbar"
app:layout_anchorGravity="bottom|right|end"/>
</CoordinatorLayout>
And I'm calling:
fab.clearAnimation();
fab.setVisibility(View.GONE);
I'm trying to hide the FAB, but it seems that setVisibility + clearAnimation does not work if the FAB is in a CoordinatorLayout.
Even if I call fab.clearAnimation, the animation is still triggered. Can anyone help me?
Use show and hide methods to show and hide the Floating Action Button
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
// To show the Floating Action Button
fab.show();
// To hide the Floating Action Button
fab.hide();
For FloatingActionButton the setVisibility() method will give you an error while building with the latest Gradle 6.x and build-tool 28.x.x and is not encouraged any more. Instead, use:
fab.hide() // fab.setVisibility(View.GONE)
fab.show() // fab.setVisibility(View.VISIBLE)
Note: Succesfully tested on Android Studio 3.4.1, Gradle 6.0 and
build-tool 28.0.1
If your issue is the animation, you could try invalidating the FAB Behavior. As for the visibility, you should null the anchor you have set in your layout:
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setBehavior(null); //should disable default animations
p.setAnchorId(View.NO_ID); //should let you set visibility
fab.setLayoutParams(p);
fab.setVisibility(View.GONE); // View.INVISIBLE might also be worth trying
//to bring things back to normal state
CoordinatorLayout.LayoutParams p = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
p.setBehavior(new FloatingActionButton.Behavior());
p.setAnchorId(R.id.appbar);
fab.setLayoutParams(p);
I ran into exactly the same issue. It would seem that Google's Android team doesn't want you to have control of the visibility when the FloatingActionButton is anchored to an AppBarLayout, as discussed in this issue - FloatingActionButton Ignores View Visibility
It looks like a viable fix is wrapping the FAB in a FrameLayout and setting the visibility on the wrapper instead, like this:
<android.support.design.widget.FrameLayout
android:id="#+id/fab_container"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:visibility="invisible">
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/fab_icon"/>
</android.support.design.widget.FrameLayout>
You may however wish to consider whether this is the ideal behaviour. Google advocates recommend that the FAB be visible as soon as the screen is created. If you're hiding it for longer than required to animate it in, consider showing a disabled state instead.
you can disable it and make it semitransparent like this
fab.setEnabled(false);
fab.setClickable(false);
fab.setAlpha(0.3f);
FloatingActionButton layers = (FloatingActionButton) findViewById(R.id.layers);
layers.hide();
It works for me, setVisibility doesn't work for FloatingActionButton as it belongs to another viewGroup that doesn't have setVisibility method.
Related
I am currently trying to use the CoordinatorLayout class to adapt a Toolbar opacity depending on a ScrollView scroll position. I succeed doing this "manually linking" the two views, listening to the ScrollView scroll events and reporting them on the alpha value of my Toolbar background.
The wanted behavior is :
The toolbar is starting in a transparent state (both text and background) and end up totally white background and black text when one view is totally scrolled.
The behavior is roughly this one : Youtube video.
Current implementation
layout file (simplified)
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<my.package.widgets.DetailsTop
android:id="#+id/layout_details_top"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<my.package.widgets.DetailsBottom
android:id="#+id/layout_details_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00FFFFFF"/>
</RelativeLayout>
Fragment implementation
public class SearchVehicleDetailsFragment extends BaseFragment<SearchContract.ParentView> {
#Bind(R.id.layout_details_top) DetailsTop detailsTopLayout;
#Bind(R.id.layout_details_bottom) DetailsBottom detailsBottomLayout;
#Bind(R.id.scrollView) ScrollView scrollView;
#Bind(R.id.toolbar) Toolbar toolbar;
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
#Override
public void onScrollChanged() {
float alpha = (float) scrollView.getScrollY() / vehicleDetailsTopLayout.getHeight();
toolbar.setBackgroundColor(getColorWithAlpha(alpha, getResources().getColor(R.color.white)));
toolbar.setTitleTextColor(getColorWithAlpha(alpha, getResources().getColor(R.color.dark_grey)));
}
});
}
public static int getColorWithAlpha(float alpha, int baseColor) {
int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24;
int rgb = 0x00ffffff & baseColor;
return a + rgb;
}
}
Problem
However, even if the previous snippets are a particularly simple solution that seems to work perfectly, I am just a little confused about why it didn't work with CoordinatorLayout. Also, I found a guy who seems to have succeed on this task with a custom CoordinatorLayout.Behavior<android.support.v7.widget.Toolbar> implementation.
You can take a look at his custom CoordinatorLayout.Behavior implementation. He also gives some details on Medium. However, due to a lot of just <android.support.v7.widget.Toolbar .../> instead of the full Toolbar tag and a strong lack of understanding of how this part of the Support Design library works, I was never able to implement it...
Question
I would like to understand how CoordinatorLayout, and all the classes around it, works together. So I will probably be able to implement the behavior I am looking for, which is : linking a ScrollView scroll position to the alpha value of a toolbar background color.
Obviously, if you also know how to implement all this, I will be really happy to see your snippet :)
I've been experimenting with behaviors, I am happy you found my article partially helpful.
I redacted the code of the Toolbar chunk because it wasn't important. Simple Toolbar attributes, nothing special about it:
<android.support.v7.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:id="#+id/toolbar"
app:layout_behavior=".view.ToolbarBackgroundAlphaBehavior"/>
I would like to understand how CoordinatorLayout, and all the classes
around it, works together. So I will probably be able to implement the
behavior I am looking for, which is : linking a ScrollView scroll
position to the alpha value of a toolbar background color.
In your layout you are missing the CoordinatorLayout as being top parent that wraps everything. Instead of using ScrollView you should use NestedScrollView it works just like ScrollView but the difference is that NestedScrollView can perform nested scrolls in older version, unlike ScrollView which nested scrolls only after API 23.
For a CoordinatorLayout.Behavior to work the target view must be direct descendant of the CoordinatorLayout. As you can see in the article, the Toolbar is direct descendant of the coordinator. Otherwise, the behavior will not work.
In the example NestedScrollView has appbar layout behavior, so that AppBarLayout can expand and collapse, you can find plenty of examples about this.
Update: I have solved this problem just by listen to the scroll change event of the NestedScrollView and do the appropriate handling there.
I'm following this tutorial to animate showing and hiding of my FloatingActionButton. But it doesn't really work for my layout. My layout is like this picture:
It has a NestedScrollView and a number of RecyclerView inside. When I scroll by touching the area of NestedScrollView, the FloatingActionButton is animated as expected. But when I scroll by touching the area of one of the RecyclerViews, the FloatingActionButton don't animate at all. When I try debug my code, I realize that the onNestedScroll method doesn't gets called when I scroll by touching on the area of RecyclerView.
Comment out or delete this code block from your xml layout
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="#drawable/ic_done"
app:layout_anchor="#id/viewA"
app:layout_anchorGravity="bottom|right|end"/>
I am using a floating action button(FAB) in my application to show Dialogs, everything is worked just fine when I tested my app in Xperia Z with Lopllipop 5.1.1.
However, the problem is when tested my app in ASUS Zenfone 6 with KitKat 4.4.2 and in Xperia C with Jelly Bean 4.2.2, the FAB loaded perfectly but the FAB does not show the Dialogs, seems like it does not responds when I touched it.
For the record, my min sdk version is 16.
What i want to ask is why this is happening? Is there anything wrong with my code, or maybe with the android version or API level?
Please take a look at my code. Here the XML code:
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_add_account"
android:visibility="invisible"
android:clickable="true"/>
and here how I declare and set the listener for the FAB:
FloatingActionButton fab;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
fab = (FloatingActionButton) getActivity().findViewById(R.id.fab);
...
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showDialog();
}
});
...
}
The thing that made me confused is how it is worked in Xperia Z but it does not worked in ASUS Zenfone 6?
The problem in here is that I declared the FAB before the declaration of listView. Somehow by relocating the declaration of FAB after the the declaration of listView it will solved the problem.
From:
<android.support.design.widget.FloatingActionButton
...
...
.../>
<ListView
...
...
.../>
To:
<ListView
...
...
.../>
<android.support.design.widget.FloatingActionButton
...
...
.../>
Just as simple as that.
Programmatically bringing the FAB to front should also work:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.bringToFront();
fab.setOnClickListener... //etc
Just add clickable and focusable and set both to "true" in FAB (floating action button) in xml file
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:clickable="true"
android:focusable="true"
/>
This enable floating button to receive click events and make clickable
Let’s pretend the simple case for simplicity. I have a FloatingActionButton on which I add a layout_behavior. I need to be able to enable or disable the behavior programmatically. How do I do that? I originally add the behavior through xml
<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="#drawable/mine"
app:backgroundTint="#color/colorPrimary"
app:layout_anchor="#id/default_message"
app:layout_anchorGravity="end|bottom"
app:layout_behavior=“mywidget.ScrollingFABBehavior"/>
You can retrieve the LayoutParams via
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) fab.getLayoutParams();
And that point you can either set the behavior directly with setBehavior():
params.setBehavior(null);
Or get your instance of behavior and call a method to have it disable itself (that you make):
ScrollingFABBehavior behavior =
(ScrollingFABBehavior) params.getBehavior();
// This is a method you write
behavior.setEnabled(false);
I have,in my code, only one activity and many fragments.
The structure is this one :
<android.support.v4.widget.DrawerLayout>
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout>
<android.support.design.widget.CollapsingToolbarLayout>
<ImageView/>
<android.support.v7.widget.Toolbar/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout/>
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView/>
</android.support.v4.widget.DrawerLayout>
and
compile 'com.android.support:appcompat-v7:23.1.0'
compile 'com.android.support:design:23.1.0'
I don't need the collapsing toolbar in all fragments but I prefered to do that instead of putting a appbarlayout in each fragment.
The problem is when I launch my app :
1) I am on a fragment where the collapsing toolbar is not usefull( I don't have scrolling content) BUT I can still expand the collapsing toolbar if I scroll on the toolbar (This is the issue...).
2) Now,I go in a fragment with scrolling content and I expand the collapsing toolbar with a recyclerview , the collapsing toolbar works normally.
3) I want to repeat the bug of 1), the bug is not present anymore.
Like scrolling with a recyclerview has solved the bug?
The collapsing toolbar does not expand if I scroll on the toolbar. And I would like it to be like till the launch of the app.
I don't won't to go on a fragment scrolling content to disable this bug.
You can see this gif which represent what I'm talking about via GIPHY
Can you help me? :)
If you want to change the scroll behavior you can do that programmatically by changing the Scroll Flags on the AppBarLayout.LayoutParams of the CollapsingToolbarLayout.
CollapsingToolbarLayout ctl= (CollapsingToolbarLayout) findViewById(R.id.collapsing_appbar);
AppBarLayout.LayoutParams params = ctl.getLayoutParams();
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);//or a combination of flags
ctl.setLayoutParams(params);
Another trick to make the CollapsingToolbarLayout scroll 'with no scrolling content' is to put
'your layout' in a NestedScrollView and set a *1000dp min height value
to the child of the NestedScrollView ('your layout').
android:minHeight="1000dp"
Layout:
<android.support.v4.widget.NestedScrollView
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!--your layout-->
<FrameLayout android:minHeight="1000dp"/>
</android.support.v4.widget.NestedScrollView>
*SupportDesignDemos example here: https://github.com/android/platform_development/blob/master/samples/SupportDesignDemos/res/layout/include_appbar_scrollview.xml