Fragment's layout is too high with TabLayout + AppBarLayout - android

I'm struggled with this for hours looking for solution on google and stackoverflow. Thought that this is some trivial bug in my app but finally made empty project and can reproduce this too. Just run new project and select "Tabbed Activity" with navigation style "Action Bar Tabs (with ViewPager)
Then try to put any widget at the bottom of the fragment's layout. I did this by modify fragment_main.xml and adding:
android:layout_height="match_parent"
android:gravity="bottom"
android:textAlignment="center"
So the whole layout is:
<?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:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity$PlaceholderFragment">
<TextView
android:id="#+id/section_label"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:gravity="bottom"
android:text="aaaaaaa"
android:textAlignment="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="#+id/constraintLayout"
tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1" />
</android.support.constraint.ConstraintLayout>
In design mode everything looks fine:
But when you run app:
You will see text only when you swipe action bar to hide it:
So it is impossible to set widget at the bottom of the tab's fragment or even match some list/picture to the height of the parent because bottom edge will be always under navigation bar.
Workaround which I found is here:
ViewPager with Toolbar and TabLayout has wrong height
First one is to put AppBarLayout and ViewPager between LinearLayout but then I lose hidding action bar functionality when scrolling ViewPager's content. Second one is add android:paddingBottom="?attr/actionBarSize" in ViewPager but then there is a gap when I hide action bar. Seriously there is no solution for this?

I think this is an expected behavior since the ActionBar gets hidden when scrolling up. In the design mode the text can be shown because it doesn't display the TabLayout. However, when you launch the app, it will inflate the TabLayout and the fragment will go below it. So it's not like the fragment is getting expanded or giving you wrong height.
Imagine putting an ImageView that has a matching height of the visible field (from below the TabLayout to right above the navigation menu). When you hide action bar from there, it will have a gap on the bottom since there's no content to fill up the space of hidden action bar, unless you stretch the ImageView as you scroll up, which will result in wired stretched image :/
One possible solution I can think of is, if you want to add a view on the bottom of the fragment, I will set the actionbar padding to the view and when I scroll the screen, I will adjust the padding depends on the scroll offset so that I can always be on the bottom.

Related

Linear Layout Overlapping Navigation Bar

I can not figure out for the life of me why and how to stop the Linear Layout from overlapping the navigation bar. I am familiar with Android Studio, just not version 2+.
This problem was never a thing and I have tried multiple searches and attempts to fix this. (Screenshot below).
Put this in your LinearLayout code in the content_main.xml file.
android:layout_width="match_parent"
android:layout_height="match_parent"
In your LinearLayout set padding top 50dp
android:paddingTop="50dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
You can change margin values depending on layout position.

Removing navigation view top padding in Android N Multi-Window mode

I would like to remove paddingTop/marginTop from the navigation view in Multi-Window mode of Android N. Like Gmail already does.
If you see the image below, I'm talking about the normal padding with size equals to the status bar at the beginning of the navigation view.
So basically in Multi-Window mode (see the image below) I have to remove that padding when my app is in the second part of the screen.
Unfortunately from the new api 24 you have isInMultiWindowMode() but it's not possible to know in which part of the screen is your app.
Instead of trying to figure out if you're in multi-window mode and on which part of the screen, you need to make your navigation view header respect system windows insets.
Normally you care about just one window - the one your app is drawn in. Usually you don't even think there are any windows. Isn't your app drawn fullscreen? Well, actually no. Usually there is some space reserved for system bars, like status bar at the top and navigation bar at the bottom. They are drawn in separate windows - system windows. (Oh, and now we've got multi-window mode in N. More like multi-app-window mode, because if you count system windows then multi-window has been around for a while.)
You can make your navigation view header adjust its insets depending on whether it is under a system window (in this case: status bar) or not with just a few simple tweaks.
Assuming the navigation view is defined like that:
<android.support.design.widget.NavigationView
...
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
... />
and there is a simple header layout in nav_header_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/nav_header_height"
android:background="#drawable/nav_header_background"
android:orientation="vertical"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="32dp">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/default_profile_picture" />
...
</LinearLayout>
you just need change it like that:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="#dimen/nav_header_height"
android:background="#drawable/nav_header_background"
android:fitsSystemWindows="true"
android:orientation="vertical">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#android:drawable/sym_def_app_icon"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"/>
...
</LinearLayout>
First you need to add android:fitsSystemWindows="true" to the layout.
Now you need to make top padding smaller, as fitsSystemWindows will automatically add padding the size of status bar. So previously your top padding was from the top of your header, now it is only from the bottom of the status bar.
And you have to move all your paddings from the layout somewhere else (for example I moved them to margins on child views), because fitsSystemWindows will overwrite those paddings.
After this if your app is in the bottom part of multi-window split then the padding for status bar will not be added. It will also make your navigation view look properly in any other cases where it's not under the status bar or if the status bar changes size in any future version of Android or some crazy custom ROM.
For me nothing was working so I ended up going this route and it got the job done:
<android.support.design.widget.NavigationView
...
app:insetForeground="#null"/>
Technically, the insets are still present but since the insetForeground resource used to draw on them is now null, that logic is skipped in ScrimInsetsFrameLayout's onDraw method (which is the parent class of NavigationView).
So when all else fails, this is a fairly efficient route.

Status bar always on screen

Good day (or evening, or night)
I'm developing an app for android and I'm very curious about one thing. I have an activity, where user chats with another, like "im" chat. There are an EditText on the bottom and some kind of actionbar on the top. What I need is when user enters a message and the software keyboard is on screen, my activity should move up, but the actionbar should still be "glued" to the top of the screen, because it has some valuable controls on it.
Again, that's not an ActionBar, but just a 48dp height layout in a parent vertical linear layout. So I need to know is there an easy way to prevent it from moving to the top, when the layout moves off the screen.
I tried to put everything in a FrameLayout and put this bar on top of it, but on keyboard opens it goes off the screen too...
On you Activity at AndroidManifest you should put this: android:windowSoftInputMode="adjustResize"
Use something like this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.myapp.MyActionBar
android:layout_width="match_parent"
android:layout_height="48dp"/>
<LinearLayout
android:id="#+id/mylayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1dp"/>
<!-- Add your edittext and button -->
</LinearLayout>
This will make sure the actionbar and edittext + button are allways on screen, and the mylayout takes up the rest of the screen. When your keyboard is shown, the mylayout will shrink.
Try adding android:windowSoftInputMode="adjustResize" to your activity in the manifest. This tells Android to completely resize your layout when the keyboard comes up, rather than pan it. Note that if there isn't enough room for the entire layout this still won't work. But you ought to be able to make it work if your top level layout is a RelativeLayout, with the edit text set to align bottom, the top bar to align top, and the middle section to fill_parent and be above the edit text and below the bar.
use a RelativeLayout as your base Layout and add android:layout_alignParentTop="true" to your action bar to keep it up
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/action_bar_layout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentTop="true" >
</LinearLayout>
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>

PagerTitleStrip is reserving space at top *and* bottom of my view

Using the latest Android Support Package v4 (December 2011), I'm trying to implement a ViewPager with a PagerTitleStrip to show the title of the three panes in my UI.
I've read the sparse docs and successfully created the title strip at the top of my view, using the following XML:
<android.support.v4.view.ViewPager
android:id="#+id/mypager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<android.support.v4.view.PagerTitleStrip
android:layout_gravity="top"
android:id="#+id/titlestrip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true" />
</android.support.v4.view.ViewPager>
However, my view now has a "gap" at the bottom of the layout, with height precisely the same as the title strip. If I increase the size of the title strip at the top of the UI, the gap at the bottom of my view also enlarges. It's as if there is a bug in PagerTitleStrip which is incorrectly placing the title strip at both the top and the bottom, even though it's only displaying it at the top.
If I set layout_gravity to "bottom" instead of top, the strip shows correctly, i.e. at the bottom of the view without any strange artifacts at the top. And if I remove the title strip, the gap disappears.
Anyone have a solution to this, or seen it in their code as well?
When you add views to your view pager in instantiateItem, make sure you call addView(view), NOT addView(view, 0).
This fixed this issue for me.

titlebar bottom

i read this tutorial how to create a custom-titlebar.
http://www.anddev.org/view-layout-resource-problems-f27/my-own-titlebar-backbutton-like-on-the-iphone-t4591.html
works fine BUT:
is it possible to add this bar not as a titlebar on the top but on the bottom?
You can always create your own TextView and place it in an absolute position on a layout (see AbsoluteLayout here) but I would recommend against this as it breaks from the normal user interface standards and could be confusing to users. In addition if you have scrolling in your layout the positioning would become more complex. As far as I know there is no built-in way of moving the title bar.
Just an idea.
You can turn off the title bar and add something like title bar to the bottom of all your layouts:
<LinearLayout
android:orientation="vertical"
android:width="fill_parent"
android:height="fill_parent">
<LinearLayout
android:id="#+id/layout_container"
android:weight="1"
android:height="0dp"
android:width="fill_parent">
...
</LinearLayout>
<LinearLayout
androdi:id="#+id/titlebar"
android:height="wrap_content"
android:width="fill_parent">
...
</LinearLayout>
</LinearLayout>
But i've never seen a title bar at the bottom.

Categories

Resources