Android constraint layout strange behavior - android

The version of my constraint layout is 1.0.0-alpha8 . After I have included a toolbar in my layout , there is space in both left and right side of the toolbar, like the image below
Here is the code for my toolbar
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
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="?attr/actionBarSize"
android:background="#color/colorPrimary">
</android.support.v7.widget.Toolbar>
Which I have included in my layout in following way
<include
layout="#layout/toolbar_top"
android:id="#+id/topPanel"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
I didn't used any additional padding or margin in my root element of the layout file .
Another stange thing is if I compile or build the program my code automatically changed, like
<include
layout="#layout/toolbar_top"
android:id="#+id/topPanel"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
Change to
<include
layout="#layout/toolbar_top"
android:id="#+id/topPanel"
android:layout_height="wrap_content"
android:layout_width="368dp"/>
And the guideline also add some additional value which I didn't write, like layout_editor_absoluteX automatically added .
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/guideline1"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.15"
tools:layout_editor_absoluteX="58dp"/>

First, you should update to ConstraintLayout beta 4.
Now, the root problem you have is that you are using match_parent on the toolbar -- this isn't supported by ConstraintLayout. You need to add:
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
and use 0dp instead of match_parent:
<include
layout="#layout/toolbar_top"
android:id="#+id/topPanel"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
Note that you can create those attributes easily by doing right-click on the component, and picking
On Android Studio 2.2 you need to hold the key to create the constraints, on Android Studio 2.3 it creates the constraints by default.

Related

How to constrain view to a view in another layout file?

My app uses a tabLayout which is defined in the main_activity layout. I then have a separate layout file per tab to place all the views for that tab.
In the tab layout files, I’d like to constrain a view to the bottom edge of the tabs. I don’t know how to do this as the tabLayout is defined in another layout file, and it doesn’t have a fixed height (and I don't really want it to), so I can’t just use the same dimension in the tab layout file.
I’ve seen that there’s an tag that you can use to pull content in from other layouts, but this doesn’t feel right, I don’t need the whole layout to be duplicated within the tab, I essentially just need to know the height of it.
Here’s my main_activity layout which contains the tabLayout.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:background="?attr/backgroundColour"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/toolbar">
<android.support.design.widget.TabItem
android:id="#+id/CostTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/cost" />
<android.support.design.widget.TabItem
android:id="#+id/costTab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/distance" />
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="#id/tabMenu"
/>
</android.support.constraint.ConstraintLayout>
You should populate the adapter for ViewPager with Fragments for each tabLayout you have or use plain views as adapter items. You can find more info in developer guide here: https://developer.android.com/guide/navigation/navigation-swipe-view

Is there an official API for centered title on Toolbar like on popular Android apps, in the new material design?

Background
In the past, Google always shown the toolbar to have the title aligned to the left:
https://material.io/develop/android/components/app-bar-layout/
However, recently, it seems that on some of its apps, the title is centered, even if it doesn't have symmetric content on the left and right. Example is on "Messages" app:
And on "Google News" app :
It also got updated on the material guidelines, here. Example:
Some people like to call it "material design 2.0", as it got various things updated.
The problem
While there are plenty of similar questions on StackOverflow from the time it was called "ActionBar" (example here ), here it's different, because it should have the support library (AKA "Android-X") have a way to handle it correctly, because things have changed, and now Google should support it as it's a part of the guidelines and part of various Android apps.
What I've tried
I tried to add a view within the toolbar, but even by coloring the view, you can see that it's not really centered, automatically, and that's before adding more action-items or up-button :
activity_main.xml
<androidx.coordinatorlayout.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"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.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">
<TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="title"
android:gravity="center" android:background="#33ff0000"
android:id="#+id/titleTextView"/>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
This solution is similar to many others presented on other StackOverflow threads similar to this question, and just like there, it fails to really center the text, while on Google's attempt, it gets centered correctly, no matter the number of action items and other views around.
There is also a nicer workaround that I've come up with: have one toolbar on each side, and make the TextView have margin that is the max of both. There is even a library for this, "Toolbar-Center-Title"... But again, this is a workaround. Not what I'm asking about.
The question
Is there now an official way to have a centered title on the Toolbar, no matter how many action items there are, and no matter what's on the other side (up button, for example) ?
If so, how can this be done?
NOTE: Again, I'm not interested in workarounds. There are plenty of workarounds and I can think of such by myself.
TL;DR: No, there's currently no official way to center the title on a toolbar.
I don't think there is an official way to do it, at least not yet. But I know that the Flutter framework supports it and it's pretty straight forward: you simply need to pass centerTitle: true to the appbar constructor, as described in this answer. And there's a good chance that the apps you've mentioned in your question were built with Flutter, since both are from Google.
I think the closest workaround to your expected layout is having the TextView on top of the Toolbar, as shown here:
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
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="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar">
</android.support.v7.widget.Toolbar>
<TextView
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"/>
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
But it would be really nice if the official Android API could support this the same way flutter does. Maybe you'd like to send a feature request to the Material Components Android Issue Tracker?
Now We have an official way to center the title on a toolbar using Material Design 3
Using Material Design 3 we can align the title in the center without doing extra work or without adding text view in toolbar
To align the title in the center We need to use the below properly
app:titleCentered="true"
To align subtitles in the center we need to use the below property
app:subtitleCentered="true"
Sample Code
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/topAppBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="Center Aligned title"
app:subtitle="Sub title"
app:subtitleCentered="true"
app:menu="#menu/top_app_bar"
app:titleCentered="true"
app:navigationIcon="#drawable/ic_android_black_24dp" />
</com.google.android.material.appbar.AppBarLayout>
OUTPUT
How about textAlignment="center"? a RelativeLayout does the trick, when AppCompatTextView has set layout_width="match_parent"; for example:
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="#+id/customView"
android:minHeight="?android:attr/actionBarSize"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="top">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Home Button -->
<include
layout="#layout/button_home_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"/>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="18sp"
android:textStyle="bold"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/app_version"
android:textAlignment="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textSize="12sp"
android:textStyle="bold"/>
</androidx.appcompat.widget.LinearLayoutCompat>
</RelativeLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
</layout>
the down-side is, that when showing several menu-items as action buttons - or when displaying extraordinary long strings as title, the title may overlap them - but when only showing one or two action buttons in combination with a title that fits the visually available width, this works just fine - that's because menu config ifRoom would always apply, because there is room. else one could only measure, which side of the toolbar has the most wide items' container - and then adjust the width on the other side's items' container. scaling the font-size depending on the available room might also be an option, to make it fit dynamically.
No official way to do it but subclassing provides most coverage without crazy tricks.
https://gist.github.com/bmc08gt/40a151e93969f2633b9b92bca4b31e83
app:contentInsetStart="#dimen/margin_64" //64dp
app:contentInsetEnd="#dimen/margin_64" // 64dp
toolabr section
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:gravity="center_horizontal"
app:contentInsetEnd="#dimen/margin_64"
app:contentInsetStart="#dimen/margin_64">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create"
android:gravity="center_horizontal"
android:textColor="#color/white"
android:textSize="18sp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>

How to find menu height

i want to create fixed navigation layout, but there is a problem when i rotate device, margin-top of this layout is more than it has to be, so the question - how can i find height of this dark-blue header ( to use it as margin ), or maybe there is another way
<RelativeLayout
android:layout_width="match_parent"
android:layout_marginTop="55dp"
android:layout_height="80dp"
android:background="#drawable/panel_border"
android:layout_alignParentTop="true">
If I were you, I would go with this:
android:layout_marginTop="?attr/actionBarSize"
This attribute indicates correct height of the ActionBar / Toolbar.
The Toolbars height may be different for different APIs and that's the reason you should use ?android:attr or ?attr (when using support library).
? means that it comes from internal Android resources.
Let the android support library do it for you. 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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<! -- Your View -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/panel_border"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<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="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
take a look at this

Can't make Floating Action Button "float"

First things first, I've checked that answer: How to add shadow to the FAB provided with the android support design library?
But even adding the app:borderWidth="0dp" or elevation="6dp" it didn't work. I have checked this answer: https://stackoverflow.com/a/30752754/1121139 it says as bigger my elevation, bigger is the shadow, and here goes the funny thing, at the preview screen it shows the shadow, but when runs at smartphone I got no shadow.
Here goes an screenshot from smartphone:
and here goes and screenshot from preview screen at android studio:
My layout code:
<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:orientation="vertical"
tools:context="amaz1ngc0de.com.br.materialdesign.MainActivity">
<include android:id="#+id/app_bar" layout="#layout/toolbar_app_bar"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_test_fab"
android:layout_below="#id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:layout_margin="16dp"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:src="#drawable/ic_add_white_24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:elevation="140dp"
app:borderWidth="0dp"
app:pressedTranslationZ="12dp"
android:clickable="true"/>
Try wrapping your layout inside a CoordinatorLayout and put the FAB at the same level, instead of a RelativeLayout, example:
<!-- main_layout.xml -->
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:fitsSystemWindows="true"
tools:context=".activity.MainActivity">
<include layout="#layout/toolbar_app_bar" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_test_fab"
android:layout_below="#id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.FloatingActionButton
... />
</android.support.design.widget.CoordinatorLayout>
Edit:
This widget is from the design library, you should have it added in your app's build.gradle file:
compile 'com.android.support:design:24.0.0'
OK so I have tried around a bit and it seems shadowing with elevation doesn't work as you imagined. This code gives quite a shadow:
<android.support.design.widget.FloatingActionButton
android:id="#+id/name_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="15dp"
android:src="#drawable/ic_add"
app:elevation="20dp"/>
But if I set elevation to 200, the shadow disappears. So there is only a range at which the shadow is working.
Maybe you can understand it as an object, casting a shadow onto an underlaying object. The higher the elevation, the greater is the distance between the two objects and the less shadow is cast...

FAB with anchor in coordinator layout has extra margin in android pre-lollipop

I have a CoordinatroLayoutwith FloatingActionButton. Here is my code:
<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"
android:layout_below="#+id/toolbar_layout"
android:layout_above="#+id/actionbar">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="120dp"
android:minHeight="?android:attr/actionBarSize"
android:background="#color/toolbar_color" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</ScrollView>
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:fabSize="mini"
android:src="#mipmap/ic_action_edit"
app:layout_anchor="#id/toolbar"
app:layout_anchorGravity="bottom|right|end"
app:backgroundTint="#color/toolbar_color" />
</android.support.design.widget.CoordinatorLayout>
But it appears differently in lollipop and pre-lollipop devices.
Lollipop:
Pre-Lollipop:
Actually I haven't add any margin. But FAB has margin in pre-lollipop devices.
I have also seen this problem in cheessesquare sample. It shows different margins too. What is the problem?
I dont think you want to place them without margins. If I understood it right, you've done this to see whats going on in different versions of android.
You can use app:useCompatPadding="true" and remove custom margins to maintain same margins across different versions of android
Proof of concept
According to this link, it seems to be a bug in android design library. It says that:
in API <20, the button renders its own shadow, which adds to the
overall logical width of the view, whereas in API >=20 it uses the new
Elevation parameters which don't contribute to the view width.
So I have to provide two resource files for margin:
res/values:
<dimen name= "fab_margin_right">0dp</dimen>
And in res/values-v21:
<dimen name = "fab_margin_right">8dp</dimen>
Since 22.2.1 version of support and design library, previous answer is no longer true. There is no extra padding if FAB is inside CoordinatorLayout.
<?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">
<android.support.design.widget.FloatingActionButton
android:id="#+id/button_show_qr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:src="#mipmap/ic_action_edit"
app:backgroundTint="#color/primary"
app:borderWidth="0dp"
app:elevation="4dp"
app:fabSize="normal"
app:rippleColor="#color/primary_dark"/>
</android.support.design.widget.CoordinatorLayout>
This code will produce following FAB on every Android version.

Categories

Resources