FloatingActionButton, layout_anchor and layout_gravity - android

A bit of a newbie here. I'm about two months into Android development, but I have years of development experience in other environments.
Okay. I have a FloatingActionButton which was not showing up where I expected it or wanted it. It's inside a CoordinatorLayout, along with an AppBarLayout/Toolbar, and following a ListView.
Here is the 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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/fragment_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ViewVehicleList">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:title="Vehicle List"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
</android.support.design.widget.AppBarLayout>
<ListView
android:id="#+id/Vehicle_ListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#FFFFFF"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</ListView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_AddVehicle"
style="#style/FloatingAddButton"
android:src="#drawable/ic_green_add"
android:layout_gravity="bottom|end"
app:layout_anchor="#id/Vehicle_ListView"
android:onClick="addVehicle"/>
</android.support.design.widget.CoordinatorLayout>
With this layout, the screen looks like this:
My layout_gravity says "bottom|end". I changed it to "bottom|right", but still I got the same result. I've read many tutorials, and researched through Stack Overflow, and have had no luck.
I managed to solve it by removing the anchor listed in the FAB element app:layout_anchor="#id/Vehicle_ListView", which seems to run a counter to what I've read: to use a FAB and position it properly you need to use layout_anchor and layout_gravity. Without the anchor tag, it looks like this:
So here's my question: Why is my anchor screwing up the positioning of my FloatingActionButton? What am I doing wrong?

You just need to add layout_anchorGravity.
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab_AddVehicle"
style="#style/FloatingAddButton"
android:src="#drawable/ic_green_add"
android:onClick="addVehicle"
app:layout_anchor="#id/Vehicle_ListView"
app:layout_anchorGravity="bottom|end" />

if you use constraint layout, you should set fab's top and bottom constraint to your desired layout edge like this. for example I have a cardview witch I want to anchor fab to it
<androidx.cardview.widget.CardView
android:id="#+id/mix_video_cardView/>
<com.google.android.material.floatingactionbutton.FloatingActionButto
app:layout_constraintTop_toBottomOf="#+id/mix_video_cardView"
app:layout_constraintBottom_toBottomOf="#+id/mix_video_cardView"
app:layout_constraintStart_toStartOf="#+id/mix_video_cardView"
app:layout_constraintEnd_toEndOf="#+id/mix_video_cardView"
/>

Related

Scroll second child in AppBarLayout

I'm trying to obtain this effect where if the user scroll a RecyclerView a certain layout scroll up together with the recycler and disappear behind a Toolbar.
A similar behavior could be obtained using the CoordinatorLayout, this would be possible by setting
app:layout_behavior="#string/appbar_scrolling_view_behavior"
on the said Recycler, and doing
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
Also, If I put a second child inside the AppBarLayout, and set app:layout_scrollFlags to it, the effect obtained is the same, with both layout scrolling together with the Recycler.
What I'm trying to achieve is to keep the first child (The toolbar) fixed in position, and let the second child (a LinearLayout) to scroll and hide behind the toolbar. Unfortunately I couldn't get to this behavior.
Is it possible without using 3rd part library?
Thanks in advance and sorry for my english.
Finally I figured out a way to achieve this behavior, by including the CoordinatorLayout in an LinearLayout and making the second child(LinearLayout) become the first, by moving the Toolbar to the extrnal(root) level
Hierarchy before:
<CoordinatorLayout>
<AppBarLayout>
<ToolBar>
<LinerarLayout>
Hierarchy after:
<LinearLayout>
<ToolBar>
<CoordinatorLayout>
<AppBarLayout>
<LinearLayout>
An exmaple:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="48dp" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorSecondaryLight"
android:orientation="vertical"
app:layout_scrollFlags="scroll"/>
</com.google.android.material.appbar.AppBarLayout>
.
.
.
.
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
Hope that helps!

Android: visibility:gone element is shortly visible

Hy,
I have the problem that a FloatingActionButton with visibility set to GONE shows up very short when opening the activity and then disappears as it should.
The button is used at a later point, that's why it must be invisible. At the moment though if somebody is fast enough (mainly on older devices/android versions), he can click the button before he should be allowed to.
My layout is pretty much the same as it was created by android studio, only that I set the visibility to gone:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:fitsSystemWindows="true"
tools:context="com.fallenritemonk.ludus.game.GameActivity">
<android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
android:layout_width="match_parent" 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_game" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/add_fields_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"
android:visibility="gone" />
</android.support.design.widget.CoordinatorLayout>
content_game.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.fallenritemonk.ludus.game.GameActivity">
<GridView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/fieldGrid"
android:numColumns="9"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp" />
</RelativeLayout>
I have no clue where the problem could be. I tried also setting it INVISIBLE instead of GONE. Since I cannot determine if the user was fast enough to press the button before he should have been able to, the only possibility to prevent him from doing so is to remove this "flashing up of the FAB"-bug.
If any more information needed feel free to ask!!!
Thanks for your help
Just add fab.hide() to your onCreate() method (or onCreateView() if using Fragment). You can remove visibility tag from xml as it will no longer be needed. If you want to show your FAB, use fab.show();
Have no reputation enough to comment, so I answer here
Try to place tag android.support.design.widget.FloatingActionButton before include. If it does not help, please, provide content of content_game
Try disabling the anchor id and after that set the visibility. It should work.
Try the following:
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
CoordinatorLayout.LayoutParams param = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
param.setBehavior(null);
param.setAnchorId(View.NO_ID);
fab.setLayoutParams(param);
fab.setVisibility(View.GONE);
// TO show again
param.setBehavior(new FloatingActionButton.Behavior());
param.setAnchorId(R.id.appbar);
fab.setVisibility(View.VISIBLE);
The problem seems to have been solved by simply updating the android support design library. I now have updated it from 23.0.1 to 23.1.1!

android Place content below toolbar

I have this layout:
<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/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
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="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"/>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fabButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="#drawable/ic_favorite_outline_white_24dp"/>
</android.support.design.widget.CoordinatorLayout>
Setting #string/appbar_scrolling_view_behavior attribute shifts the RecyclerView by the height of the Toolbar.
But what if I need the first element of the RecyclerView to be aligned to the status bar.
I want the Toolbar to cover (be above) the first element.
In other words, I don't want any offset which #string/appbar_scrolling_view_behavior behaviour entails.
Could you please tell me how to do that?
I had the same problem and I just wrapped the AppbarLayout and the rest of my views (in your case the recyclerview) in a RelativeLayout and it works fine. I don't know if there are any downsides with that approach.
The offset is not by #string/appbar_scrolling_view_behavior behaviour it's due to AppBarLayout it pushes the content down.
I'm not sure if there is any other better solution. But I'd suggest to remove the AppBarLayout to have your content go under the Toolbar. Moreover you might be need the scrolling behaviour for that you can check the library below.
It's been used by lots of apps like Jair Music Player even WhatsApp too uses it.
Library:
Android Observable Scroll View

Using AppBarLayout and CollapsingToolbarLayout without a toolbar

There's not many examples of these new layouts out on the Internet and those few that are out there are all based on same basic approach. How about if I don't have a proper toolbar in my app, but still want to use the cool functionalities of new material design layouts?
One thing that I've been trying out is using a MapView and RecyclerView inside CoordinatorLayout with a parallax scrolling effect. It works great, but there's a problem. If my adapter count is low, the RecyclerView doesn't remain on the bottom of screen. Here's some images to better describe the problem.
Initial screen:
RecyclerView scrolls over MapView, leaving blank space below:
Is there a way to keep RecyclerView on bottom?
My xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<com.google.android.gms.maps.MapView
android:id="#+id/tts_main_map"
android:layout_width="match_parent"
android:layout_height="250dp"
app:layout_collapseMode="parallax" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
Try to set the android:minHeight property of the CollapsingToolbarLayout dynamically depending on how many items you have in the list. I.e. you should set (pseudo-code):
minHeight = allAvailableHeight - (oneListItemHeigh * listItemCount)
PS. It just an idea, I did not tried. But I think it should works.

Overlaying content above AppBarLayout using new Material Design

I want to achieve something like that. (not the FAB or the Snackbar). How can i create a layout, overlaying the AppBarLayout? Like this! (For Example)
Like Play Store:
My AppBarLayout with CoordinatorLayout and NestedScrollView with RelativeLayout as content looks like this:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="#dimen/_118sdp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="#color/mpc_pink"
app:expandedTitleMarginStart="#dimen/_40sdp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<de.mypostcardstore.widgets.ItemImageView
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#color/mpc_pink"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7" />
<android.support.v7.widget.Toolbar
android:id="#+id/article_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:minHeight="?attr/actionBarSize"
app:contentScrim="#color/mpc_pink"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" />
</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:background="?android:colorBackground"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
android:layout_width="match_parent".....>
It would be awesome if someone could help me out. I can not find anything on the internet...
Thanks in advance!
Just add something like
app:behavior_overlapTop="64dp"
to your NestedScrollView and it will be placed above the expanded toolbar.
In addition, you should add something like
app:expandedTitleMarginBottom="70dp"
to your CollapsingToolbarLayout so the title does not appear under your overlaid scroll content.
It's quite simple, really. You could achieve that by using a combination of ToolBar, FrameLayout, and your content view (could be a ListView like your first example, or anything).
The idea is to make your FrameLayout possess the same color as your ToolBar, giving the illusion of ToolBar being much larger than it is. Then all that is left to do is to make your content view be the last (or in API 21 and above: possess the highest elevation attribute) so that it would appear as if it floats above the aforementioned FrameLayout.
See my illustration below:
Now that you got the big idea, below is some real live XML snippet for doing such thing. (I actually use this layout in one of my apps) :
<!-- Somewhere in your layout.xml -->
....
<android.support.v7.widget.Toolbar
android:id="#+id/tb_toolbar"
android:layout_width="match_parent"
android:layout_height="#dimen/abc_action_bar_default_height_material"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:contentInsetStart="72dp"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<!-- This is the 'faux' ToolBar I've been telling you about. This is the part that will be overlaid by the content view below. -->
<FrameLayout
android:id="#+id/v_toolbar_extension"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_below="#+id/tb_toolbar"
android:background="?attr/colorPrimary"
android:elevation="2dp"/>
<!-- Normally, I use this FrameLayout as a base for inflating my fragments. You could just use put your content view here. -->
<FrameLayout
android:id="#+id/ly_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/tb_toolbar"
android:elevation="3dp"/>
....
Note that my ly_content has higher elevation value than that of v_toolbar_extension. This is what will give you that desired 'overlaid toolbar' effect.
Last but not least, you would want to add this line somewhere in your activity's onCreate() :
/* Assuming mToolbar exists as a reference to your ToolBar in XML. */
setSupportActionBar(mTbToolbar);
getSupportActionBar().setElevation(0);
What that codes woud do is to set your ToolBar elevation to zero; removing preset shadows that were given as a default to ToolBars. If you don't do this, said shadow will create a "seam" between your ToolBar and your FrameLayout, thus breaking the illusion of those two being the same.
p.s., It is also important to give your content view a padding on each side. Doing so, your content view will not cover the entire width of the screen (which would render this effect useless).
Note: I see some good answers here that mentioned the absence of FrameLayout and instead making the ToolBar taller. While in theory it might work as well as my proposed solution, you might have problems when trying to manipulate scrolling; by doing that, you won't be able to separate ToolBar and its extension. You'll be forced to either make the Toolbar static or scroll all of the ToolBar altogether (makes scrolling a bit weird).
Add to that, the fact that you can't easily assign a custom drawable into a Toolbar. Hence makes it hard to follow the Google Play example you've given above. While if you're using my solution, all you'd need to do is just make your Toolbar transparent and assign the drawable to the FrameLayout instead.
I had a similar requirement and I achieved it as below.
Your activity theme should extend Theme.AppCompat.Light.NoActionBar.
I created a Layout XML File as:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="#dimen/action_bar_size_x2"
android:background="#color/colorPrimary"
android:minHeight="?attr/actionBarSize" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="#dimen/action_bar_size"
android:orientation="vertical" >
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="#string/app_name"
android:textSize="24sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
And the Activity should be something like this:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar maintoolbar = (Toolbar) findViewById(R.id.toolbar_main);
setSupportActionBar(maintoolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
I got a view like this :
I did try to implement effects like you referred which is called Card Toolbar in Android, and it did work as expected. Here is my layout, Take a look at it:
<FrameLayout 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"
android:background="#color/background_material_light" >
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="#dimen/toolbar_double_height"
android:background="?attr/colorPrimary" />
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="#dimen/cardview_toolbar_spacer"
android:layout_marginRight="#dimen/cardview_toolbar_spacer"
android:layout_marginTop="?attr/actionBarSize"
app:cardBackgroundColor="#android:color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:alpha="0.12"
android:background="#android:color/black" />
</LinearLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
Hope you'll be inspired.

Categories

Resources