ListView only renders one item unless height is specified - android

i have a context-menu with items in a ListView, all contained within a BottomSheet from the ASL/Design lib. The activity's root view is a CoordinatorLayout as specified by BottomSheetBehavior.
The problem I'm facing is that the ListView (R.id.problematic_list below) only renders the first list-item if the list-view-container's height is either wrap_content or even match_parent (R.id.list_container below). If this list container has a generous height set (eg: 400dp) then the full list renders as expected; along with extra space (since height is over-specified). The ListView is dynamically populated so I can't set a static height in the layout-xml file.
Is there a simple layout, attribute or programmatic workaround for allowing the ListView to both populate and render without over-allocating vertical space?
My initial configuration is as described here
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/primaryBlue"
android:orientation="vertical"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"_elevation" />
<!-- main activity content -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
/>
</RelativeLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="true"
android:layout_gravity="bottom"
app:behavior_hideable="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<!-- layout_height= 300dp / wrap_content -->
<LinearLayout
android:id="#+id/list_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/problematic_list"
/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

the NestedScrollView has its own set of height requirements in order to render fully. I removed it from the hierarchy and the list renders in all available space.
thanks #CoderP for the hint

Related

Position a view below a RecyclerView

I have a very simple question that for some reason im not being to able to implement.
I have a RecyclerView which is being filled only once upon its activity creation. I want to add another view below it.
If the RecyclerView doesnt fill the entire screen length (usually in portrait mode) the view should be positioned directly below it.
If the RecyclerView exceeds the screen length (usually in landscape mode) the view should still be positioned below it but should also be docked to the screen bottom.
Thats it.
I've tried position them in RelativeLayout, LinearLayout or CoordinatorLayout. With match_parent, wrap_content (with or without setAutoMeasureEnabled). With app:layout_anchor and app:layout_anchorGravity but nothing is working.
Appreciate any help.
This is an example of one of my tries:
<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.AppBarLayout
android:id="#+id/app_bar"
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.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/features_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_anchor="#id/features_list"
app:layout_anchorGravity="bottom" />
</android.support.design.widget.CoordinatorLayout>
Try this:
Note: I'm using a ScrollView since you said the height of your RecyclerView can exceed the screen size.
<?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="match_parent"
android:orientation="vertical">
<!-- Required for the content to not exceed the screen -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:measureAllChildren="true">
<!-- Content -->
</ScrollView>
<!-- View that needs to be under the ScrollView or
clipped to the button of the screen based on the ScrollView height -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</RelativeLayout>
</LinearLayout>
</LinearLayout>

Making CardView width match parent even when elevation > 0

I wanted a cardview similar to this:
I wanted my CardView separated like that. The problem is, I don't know how to make CardView go edge to edge or match the width of the CardView to its parent. If I put shadows or setting the elevation at 4dp/8dp, the entire CardView adjusts to show the shadows on both end. Which is not what I want. This is worse when viewed on pre-lollipop.
I am believing this is just thick line separating it which can be done creating custom view with a custom drawable. But can this be done with just CardViews? I need my CardViews to go to the most edge and show separation at the bottom.
Here is my current layout. I created a separate layout file for each CardViews and included them in my fragment like this:
<LinearLayout
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:fillViewport="false"
android:fitsSystemWindows="true"
tools:context="com.neonwarge.android.notifire.activity.TaskActivity"
android:orientation="vertical">
<include
layout="#layout/cardview1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include
layout="#layout/cardview2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
....
</LinearLayout>
And here is what generally a CardView looks like:
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true"
app:cardPreventCornerOverlap="false">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingStart="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingEnd="#dimen/activity_horizontal_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
android:layout_marginTop="#dimen/activity_vertical_margin">
...
</RelativeLayout>
</android.support.v7.widget.CardView>
</merge>

android space under appbar

I'm trying to place two Fragments next to each other, but I can't get rid of a space between the ActionBar and my application contents :
Here is my XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="horizontal" android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:elevation="0dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.tce.manager.MainActivity"
tools:showIn="#layout/app_bar_main">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="2dp"
android:name="com.tce.manager.DeviceListFragment"
android:layout_weight="3"
android:id="#+id/fragment_device_list" />
<FrameLayout
android:background="#android:color/darker_gray"
android:elevation="0dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
I already tried to change margins and padding for the Toolbar and AppBarLayout
Remove android:fitsSystemWindows="true"
If it's set to true, then it adjusts the padding of this view to leave space for the system windows.
Try removing the top padding between the action bar and fragment. Android Studio sometimes adds the top padding. Also, change the constraints so that Fragment renders properly

CoordinatorLayout moves content

I have a CoordinatorLayout, AppBarLayout, Toolbar and main content in the form of NestedScrollview and stuff inside it:
<android.support.design.widget.CoordinatorLayout
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:fitsSystemWindows="true"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fitsSystemWindows="true"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
/>
</android.support.v4.widget.NestedScrollView>
In the picture above, the blue section is the NestedScrollView (i.e., the main content). As you see, its height is calculated with no regard to toolbar and is just moved out of the screen.
If you replace the CoordinatorLayout with any other layout, the NestedScrollView fits well (again, the blue part is the content, i.e., the NestedScrollView):
Is it how it should behave by design? If so, how to make the NestedScrollView fit the remaining screen wholly without moving its part below?
Update: If I remove behavior on the NestedScrollView, it moves back to top, but then gets covered by the toolbar.
Update 2: Sorry if it wasn't clear, but the main idea for using the CoordinatorLayout was the ability to apply various behaviors, including the default one provided. I have some user entered text that potentially may not fit into the screen, so I surround it with NestedScrollView. Now, to ease entering the text and have more space available, I'd want the toolbar to scroll out when scrolling and typing into this input (because adjustPan and adjustResize are not ideal)
Try surrounding it with the <LinearLayout> . I mean, after the Coordinate Layout.
Use weights attributes of LinearLayout ( If necessary ) .
Set Width and height of the Nestedscrollview as Match_parent or fill_parent.
Another thing, you actually don't want to worry about the issue you specified above. It should work well when you execute.
Here is the code with <LinearLayout> . Using this tag inside will give us flexible alignment. It may be difficult at first time , but use it and practice surely it will do a trick.
Here the NestedScrollView is fixed inside the screen.
<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"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/third"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world"
/>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
Its Pretty simple.You can try this in 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"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parentlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity"
android:animateLayoutChanges="true">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="#dimen/margin_16"
app:expanded="true"
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>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
>
<!-- Your Entire Code goes Here -->
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
Your View will look like this
In case anyone is still interested in this issue, I guess I have the explanation why this happens.
So the main issue here is the AppbarLayout and it's ability to add scrolling behaviours when it's used with a CoordinatorLayout. Let's say you want to scroll away the toolbar when a user scrolls down on the view below the AppbarLayout (Let's say you have a ViewPager). Then the OS also needs to scroll that ViewPager up to fill the space on the top of the screen. But when that happens if the ViewPager doesn't have enough height to fill the entire screen, then there would be a space on the bottom. That's why the system adds an additional height (which is exactly the same height as the AppbarLayout has) to the bottom of theViewPager, to fill the space on the top, in case the AppbarLayout scrolls away.
If you look at the problem in this way, this is something that needs to be done to have a consistent view. So either you have to remove the AppbarLayout or decide not to use scrolling behaviours.

Overlap sibling view with RelativeLayout

I have a RelativeLayout at the top of my app. Below the RelativeLayout I have a ViewPager.
To explain this in a way that will make sense, imagine the screen's height is 700 pixels. The RelativeLayout is about 200 pixels high.
I want the RelativeLayout to be position absolutely at the top of the app such that the ViewPager is behind it. I then want to add a 200 pixel paddingTop to the ViewPager so that it appears under the RelativeLayout.
Here is the layout I have now (which is obviously not working):
<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="match_parent"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
I load a ListView with some data under the header:
<LinearLayout
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">
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
How can I do this?
Try changing the linearlayout to a framelayout. This will allow the views to be placed on top of each other.
Then put the code for the pageviewer above the relativelayout. This will make the pageviewer appear to be behind the relativelayout as it is rendered first, and the relativelayout rendered on top of it. Android will render views in the order in which they are declared.
Lastly, add a top margin/padding to the pageviewer to make it seem positioned below the relativelayout.
Here's what you can do:
Use RelativeLayout instead of LinearLayout as the root.
Move the ViewPager(pager) view to the top of child RelativeLayout(header)
<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="match_parent" >
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:paddingTop="200px"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</RelativeLayout>
</RelativeLayout>

Categories

Resources