Android UI: align a fragment above another fragment that is aligned bottom - android

I haven't developed for Android in more than a year and I'm a bit rusty with it. I'm trying to setup a kinda simple UI: a bottom bar at the bottom of the screen and a fragment above it (but without filling the whole height). Something like this:
I thought this would be quite simple, but after a while struggling with it I can't manage to make it work without some "hacks".
The bottom bar is also implemented as a Fragment. This is my XML:
<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"
android:orientation="vertical" >
<fragment
android:id="#+id/bottomBar"
android:name="com.mytestpackage.BottomBarFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<FrameLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#id/bottomBar"
android:layout_alignParentBottom="true" />
</RelativeLayout>
The Fragment in fragmentContainer is dynamically loaded from code. With the code paste above, fragmentContainer is aligned bottom but it's not above bottom bar, they're overlapped. If I remove the alignParentBottom from fragmentContainer, then it's placed in top of the screen.
Like I said, I found two "hacks" to solve it but I don't like them much:
1- Set a padding/margin bottom to fragmentContainer.
2- Use a filler empty layout on top of the screen and set fragmentContainer to be below that one.
Is there any way to achieve the layout I want without having to use some tricks like the ones I said?
Thanks!

Add to the relative layout:
android:gravity="bottom"
Ah, and android:orientation="vertical" is meaningless for RelativeLayout
A simpler solution would be to use a LinearLayout with vertical orientation and gravity bottom instead of the RelativeLayout.

Related

RecyclerView (wrap_content) inside of a BottomSheetDialogFragment

I'm facing a tricky situation here and I don't know how to solve this problem.
In my project I have a custom BottomSheetDialogFragment and in the layout a FrameLayout to add or replace Fragments.
Now I have a Fragment and inside I have a RecyclerView with the height:="wrap_content" because I want the BottomSheetDialogFragment only use the necessary space. Everything looks great, the problem appear when I put another view inside of the same layout and set the RecyclerView bellow or above of that view.
The RecyclerView ignores the size of the other view (or views) and always grows to the max screen size, and then it's no possible to see a few elements and even scroll.
I saw a solution, some developers are suggesting to add paddingBottom equals to the height of the view. But in my case doesn't works because I want to have a dynamic solution.
Above I'll share a few images of the problem and GitHub Repository with a sample.
Thanks for your attention!
I've manage to do what you need just need to use this as your fragment_sample.xml:
<LinearLayout 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="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/rclItems"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"/>
<Button
android:id="#+id/btnAddMoreItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/rclItems"
android:text="#string/add_1_item"/>
</LinearLayout>
Explanation
Using a LinearLayout gives you the ability to work with weight, and the vertical orientation allows you to place an item below the other. The weight on the recyclerview will increase the height of it as needed until filling the screen. The next item you add would be added to the recyclerview but you'll need to scroll the list to see it
The android developers blog says that :-
The scrolling containers in your bottom sheet must support nested scrolling .
Try changing your fragment_sample.xml as below to make the recyclerview scroll working and to make the add button persistent.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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="wrap_content">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:id="#+id/next"
android:layout_above="#id/btnAddMoreItems"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/rclItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.v4.widget.NestedScrollView>
<Button
android:id="#+id/btnAddMoreItems"
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content"
android:text="#string/add_1_item"/>
</RelativeLayout>
Note: making bottomsheet layout a child view of CoordinatorLayout will allow you to get the implement BottomSheetBehavior and recieve its transitions callbacks .

Dropshadow on Viewpager Fragment

I would like to put a shadow on the right side of a fragment inside a viewpager. An example would be the Shazam app, when you swipe the first view across, it has a shadow to the right.
I attempted to do this by creating a 10dp wide gradient the height of my main fragment (which is a relative layout, and setting it to align to the right of the parent, with a -10dp margin on the right. Unfortunately, nothing is drawn once it's moved outside of the fragments relative layout.
The xml for my main fragment is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/homeFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/home_background"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/homeShadow"
android:layout_width="10dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="-10dp"
android:background="#drawable/home_shadow"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
I have searched and can not find anything that says whether I can draw outside of the fragments relative layout or not. I found a clipChildren setting which I attempted on the relative layout and elsewhere to no effect.
Is there a way to have something drawn outside the boundaries of the fragments relativelayout?
If not, any suggestions on getting a shadow drawn to the right of a fragment as you swipe it across the screen?

Force android to scroll further than it does

as you can see, I've a bottom bar (its not using TabHost or anything, partially because obviously its depreciated but also partially because this is only on two activities in the app so I don't need to do a tab host for just two pages). Anyway there is content 'under' that tab bar. Android won't scroll any further because as it sees it that content is viewable, yet it isn't really.
My question is whats the best way to get that content up above the tab bar.
Some ideas I had:
transparant image of a set height (since the tab bar is set height) and a width of wrap_content. This isn't working.
use the background of the tab bar and make it look inconspicuous.
Make the bottom bar not transparent and put anything there, with a set height.
You might be interested in my xml structure:
<RelativeLayout>
<ScrollView>
<LinearLayout>
<RelativeLayout>
<LinearLayout>
</LinearLayout>
<LinearLayout>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>
<LinearLayout>
TAB BAR
</LinearLayout>
</RelativeLayout>
if your TAB BAR has fixed height than you can set ScrollView margin bottom attribute. This will always show your ScrollView data above the TAB BAR
Alternatively to #Antarix Tandon's answer, you could change your root relative layout to be a vertical linear layout.
RelativeLayout happily lays all its children on top of each other unless specified otherwise. Some ideas to fix it:
Change the top RelativeLayout to a LinearLayout with orientation="vertical" and ScrollView layout_weight specified to a nonzero value so that the tab bar is always in bottom and the scroll view takes up all remaining vertical space.
Keep the RelativeLayout but layout the tab bar first with layout_alignParentBottom="true" and then your scroll view with layout_above="#id/your_tabbar_id".
Give the tab bar a view id in the xml, then set the view that appears behind it to be "layout_above" the tab bar view, and make sure they are both inside the same RelativeLayout.
So, for example:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/bottom_bar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<LinearLayout
android:id="#+id/top_area"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/bottom_bar"
android:orientation="vertical" />
</RelativeLayout>
This will cause the content behind to be pushed above, and you can then put that top_area layout into a scrollview, which will then be scrollable and always sit above the bottom bar.
For example:
<ScrollView
android:id="#+id/scroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/bottom_bar" >
<LinearLayout
android:id="#+id/top_area"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" />
</ScrollView>
This will place the scrollview above the bottom bar, with the top_area layout contained within it and scrollable

Using a nested LinearLayout

SOLVED: The layout_height parameter was set to Match_parent in the buttonbar definition. Changed to wrap_content.
I'm currently working on a new App which has a series of buttons at the top of the main screen. the "buttonBar" XML defines a linearLayout and is later nested within another linearLayout.
The buttons appear fine and work however if I then put a text view beneath the include statement the text does not appear. I think that it is actually appearing behind the buttons. I assumed that because it was within a parent linearLayout that it would appear after the included (nested) nested layout.
please could someone explain why this is not occurring and point me in the right direction to solve it.
much appreciated,
M
<?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"
>
<include layout="#layout/buttonheader"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:id="#+id/textView1"
android:textColor="#ffffff">
</TextView>
</LinearLayout>
Set height and width of the included layout buttonheader
SO that you can see this included layout in your layout

LinearLayout, RelativeLayout, etc. margins do not work as expected

Margins in group layouts do not seem to work.
For example,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_margin="40dip"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="I'm a button" />
</LinearLayout>
should display a button with 40p margins on all sides. However, it has 80p margins on the right and bottom.
Am I doing something wrong?
Is this a bug?
A workaround would be to use gravity, but this only works with even margins.
BTW, there is a similar question posted here but has not been answered.
android:padding="40dp" on the LinearLayout or android:layout_margin="40dp" on the Button will give you the effect you want. Padding defines the space between a views edges and its content, layout margin defines extra space on the sides of a view.
The problem is actually the way FrameLayout interprets margins. setContentView() attaches your "main" layout to a FrameLayout, which is the actual root of the view hierarchy (you can see that with Hierarchy Viewer) and is offered to you by the phone.
Margins are managed by the parent layout, so in this case that main FrameLayout. I don't know if it's a feature or a bug, but that's how this layout interprets margins.
So well, the solution was already posted while I was typing: use padding instead.
if you need set margin for a layout, simply wrap it with another linear or relative layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:layout_margin="40dip"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="I'm a button" />
</LinearLayout>
</LinearLayout>
Wrapping the Linear Layout with another layout is the best strategy.

Categories

Resources