Scroll view shifting down on enabling navigation bar in Android - android

I am using fragments to display an image using ImageView, and ScrollView below the image view having some text using TextView in a RelativeLayout. Now the problem is that as seen in the image here there's a space created between the image and the scroll view when ever the navigation bar is enabled.
By enabling show layout bounds in the developer options, it's the image view creating the white space as seen here. There's no such space when viewed in the graphical layout on Eclipse.
Here's my xml of the fragment
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:fitsSystemWindows="true"
android:src="#drawable/city_image" />
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/imageView1"
android:clipToPadding="false"
android:fitsSystemWindows="true" >
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:padding="16dp"
android:text="#string/fragment_main" />
</ScrollView>
</RelativeLayout>
I am new to Android and I apologize if I am making a silly mistake. I have tried to change scroll view's gravity to top and also played with layout_height. But still can't figure out what is wrong in my xml.

Related

Hiding xml object if there isn't enough room on the device's screen?

The main layout for an app I'm writing is on RelativeLayout with a LinearLayout and a FrameLayout inside. In the LinearLayout, there's the buttons and text and stuff the user actually interacts with. Inside the FrameLayout, there's a graphic. The FrameLayout stays in the bottom-right corner and the LinearLayout is at the top.
When displayed on most different size screens, this layout works great. However, there is one device whose screen is too small and just an annoying little bit of this graphic shows. Is there a way to automatically disable an object if there isn't enough room for it in the XML? I know I could programmatically calculate it, but I'm wondering if there's a better way
Here's a the relevant parts of my layout file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="#+id/buttonLayout">
</LinearLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_below="#id/buttonLayout">
<ImageView
android:layout_width="139dp"
android:layout_height="48dp"
android:layout_gravity="bottom" />
</FrameLayout>
</RelativeLayout>

Setting maximum height on RecyclerView

I have a dialog fragment that contains linear layout that involves a titleText above a RecyclerView, and at the very bottom, there's a button below the recyclerView.
Since a recyclerView expands or collapses based on the number of items the adapter sets, the button sometimes gets truncated and no longer appears to be on screen, since the recyclerView just covers the entire screen.
My question is, is there a way to set the maximum height of the recyclerView without ever hiding the button underneath. I also don't want to just give the view a random height just in case the recyclerView contains no items, and it would just be a blank section.
Please let me know if you've ever run into this issue, and how you resolved this. Thanks!
UPDATED
You can achieve this easily using layout weights. Here's an example:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:gravity="center"
android:text="Title"
android:textSize="21sp"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="30dp">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="Submit"/>
</FrameLayout>
The Title and RecyclerView will wrap content according to contents and button will always take up bottom place.
I suggest using RelativeLayout as it handles the positioning of views for cases like yours, so that you can actually focus on main design.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:text="Some title" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/title"
android:layout_above="#+id/button"/>
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:gravity="center"/>
</RelativeLayout>
Above XML code is the skeleton code for what you need. you can add margins and dimensions to control the spacing. But in any case (until you provide negative margins) your views will never overlap each other.
Main trick of using RelativeLayout is the ability to use XML tags like
android:layout_below or android:layout_above or android:layout_start
or android:layout_end which perfectly aligns your view the way you
want.

Custom view shrinking: previously occupied space is not cleared

In a custom view, OnMeasure and OnSizeChanged is used to set the instrisic size and get the final size respectively.
In OnDraw, a drawable is drawn using the current Width/Height.
Now if the view is told to change its intrisic size, it will requestLayout. This triggers OnMeasure/OnSizeChanged and finally OnDraw.
It works fine, the drawable is always displayed using the correct inner size.
The problem is, if the new inner size is smaller than the old one, android leaves the old drawing (which seems to be "under" the new one, but in fact should have been cleared by android).
I tryed to clear the view content inside OnDraw, but the drawing rectangle is alread clipped to the new view size.
It sounds like a bug in LinearLayout not clearing its content when a child's view size shrink. Testing on Android 4.4 / Samsung S3 4G / CyanogenMod cm-11-20151004-NIGHTLY.
Layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/content"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000"
android:padding="8dp">
<LinearLayout
android:orientation="horizontal"
android:id="#+id/content"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="top">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#CCD39F">
<MyCustomView
android:id="#+id/myview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
What i see after updating the custom view size. Only the "black part" should be displayed, not the white one.
It should be something like this instead:
I found the problem and a workaround.
The real problem is in LinearLayout. From Android 4.0.3 to Android 6. When this vertical linearlayout has weight=1 and height=0dp, and it has only one child which height is smaller than the available height. The first time this child is drawn, no problem. If the height of this child shrink, the area below it is not repainted. So it stays with the old content of the first child, instead of being refilled with the layout background color.
In the following layout code, i demonstrate the problem and solution. The solution is to add a second child which will take the rest of the free space below the first child. Using this technics it works as expected when the first child shrinks, the second one expands and the newly "empty" space is repainted correctly.
So it is really a bug in LinearLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#000000">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#CCD39F">
<MyCustomView
android:id="#+id/icon"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- Solution. To see the problem, remove the following layout -->
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#111111" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="right">
<Button
android:text="Other demo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btnNextImage" />
<Button
android:text="Next SVG"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btnGoEmpty" />
</LinearLayout>
</LinearLayout>

Adding layout to a scrollview gets eaten up

I have a layout something like this:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="10dp"
android:background="#ff303f"
android:id="#+id/layout">
<ImageView
android:id="#+id/picture"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"/>
<Button
android:id="#+id/cancel"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_alignRight="#id/picture"
android:background="#drawable/cross_out"/>
</RelativeLayout>
I inflate it using the usual layout inflator service, set up some functionality to the button and an image to the imageview (all images are of same size and aspect ratio).
After that, I add this view to my fragment's layout which is nothing but a ScrollView which is a parent, it has a child linear layout that I call 'map' and simply add it to the map.
Expected : The added layouts should get added properly and I can scroll through it.
Actual : If more than 2 are added, the first one gets eaten up. I can see it half or sometimes it is completely eaten up. :\
Any idea whats going on here? Thanks a lot for your time.
EDIT:
Here's the layout file I add the inflated layout into:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f6ff45">
<LinearLayout
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#43ff44"
android:orientation="vertical"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_marginTop="15dp">
</LinearLayout>
</ScrollView>
I also forgot to mention that after adding 3 or more of these layouts, I realized there's unnecessary empty space in the end. :\
If you have some android:layout_gravity or gravity property in your ScrollView, that may be the reason. Try deleting it, or make it center_horizontal.
Try this code for your layout file;
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f6ff45">
<LinearLayout
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#43ff44"
android:orientation="vertical"
android:layout_margin="10dp"
android:layout_gravity="center"
android:layout_marginTop="15dp">
</LinearLayout>
</ScrollView>
As I mentioned before, android:layout_gravity="center"in this LinearLayout causes this problem. Because it doesn't only horizontally center but also verticelly center the contents. It means when they are longer than the available height, the center part will appear. I only changed it into android:layout_gravity="center_horizontal" and the problem is fixed.

Grid layout last rows being cut off

I have a layout which holds the grid layout as follows
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:id="#+id/gridview_gallery_mine"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10sp"
android:background="#color/background"
android:gravity="center"
android:horizontalSpacing="4dip"
android:numColumns="4"
android:padding="4dip"
android:stretchMode="columnWidth"
android:verticalSpacing="4dip" />
<RelativeLayout
android:id="#+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" >
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/empty_list" />
</RelativeLayout>
</RelativeLayout>
The problem is that, the last rows of the grid is being cut to half. I mean the last row is only half visible. I tried giving the gridview and also its parent (RelativeLayout) padding, margin but nothing works. BTW I have this layout inflated inside a fragment with the tabs.
P.S I am learning android design. Thanks.
I had used the combinations of
Android basic actionbar,
tabhost from support library.
The answer to above question was since i had no other options for implementation, Applying padding bottom on the parent node of the content made it work.
I tried another combination with the Toolbar in appcompat v7.21 (or 21), It worked without the extra padding, So i dint get time to investigate who causing the problem, actionbar or tabhost.
~ Hope it helps

Categories

Resources