I switched to CoordinatorLayout/AppBarLayout mainly to utilize app:layout_scrollFlags="scroll|enterAlways" (view peeks from the top when scrolling upwards). I'm using a RecyclerView without a NestedScrollLayout as the second prevents the view from recycling and after loading a lot of items it starts to lag.
The "peeking" view is the AppBarLayout and it's being resized when clicked in order to show/hide filter options. Everything works as expected, except that when resizing the AppBarLayout (by setting child views visibility), it seems like the whole layout is being rendered, for a mere moment the RecyclerView is "jumping" to the top and then back to the expected behavior. It's very very quick yet very annoying. When replaced with a LinearLayout it doesn't happen, but obviously the view doesn't peek.
My layout:
<?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:id="#+id/fragment_notifications"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:animateLayoutChanges="true">
<android.support.design.widget.AppBarLayout android:id="#+id/fragment_notifications_filter_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:animateLayoutChanges="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
app:layout_scrollFlags="scroll|enterAlways">
<!--Two example views with different heights, of which only one is visible at a time -->
<ImageView android:id="#+id/view1"
android:layout_width="match_parent"
android:layout_height="68dp"
android:src="#drawable/ic_launcher"/>
<ImageView android:id="#+id/view2"
android:layout_width="match_parent"
android:layout_height="44dp"
android:src="#drawable/ic_launcher"/>
...
</RelativeLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/fragment_notifications_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/fragment_notifications_notifications"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scrollbars="vertical" />
</FrameLayout>
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>
The Java code is pretty simple; just setting the visibility of views inside the AppBarLayout:
someViewInsideAppBarLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
Any idea how to deal with this? Thanks!
I had to enable the transition of type LayoutTransition.CHANGING (disabled by default) in the ViewGroup that has the appbar scrolling behavior (in my case it's the SwipeRefreshLayout).
LayoutTransition layoutTransition = swipeRefreshLayout.getLayoutTransition();
layoutTransition.enableTransitionType(LayoutTransition.CHANGING);
Later on I faced additional odd animation behavior that was solved by changing the LayoutTransition.CHANGE_DISAPPEARING value of the parents of the disappearing view(s) to 0 (originally 300):
relativeLayout.getLayoutTransition().setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
appBar.getLayoutTransition().setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
coordinatorLayout.getLayoutTransition().setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 0);
Related
I have a NestedScrollView under AppBarLayout with only one child - LinearLayout. Both of them have no padding and no margin on top, but still there is some space left (belonging to NestedScrollView, as I can see, setting color for the background) on top of the NestedScrollView. How to remove it?
I have tried setting android:fillViewport="true" in NestedScrollView, but got no result.
UPD: this space interacts with clipNoPadding flag, but setting all paddings to 0 does not help.
<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">
<android.support.v4.widget.NestedScrollView
android:id="#+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:background="#color/colorAccent"
android:fillViewport="true"
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary"
android:orientation="vertical">
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
// and some more buttons, just to fill the space
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true"
android:background="#color/colorTransparent">
// I omit some code, as not-belonging to the question
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
how it looks
The android:fitsSystemWindows="true" attribute will add some (usually, but not always, 24dp) top padding to the view it is applied to. This is meant to be used alongside a transparent or translucent status bar (or navigation bar), so that your view's content doesn't appear "under" the status bar.
In your screenshot, it doesn't look like you're using a transparent status bar, so this will just add 24dp of padding that you don't want. Remove it.
Note also that android:fitsSystemWindows will override any other padding on the view that uses it. So even if you set the padding to 0 manually, you'll still get 24dp padding.
I have a ListView in a Fragment which isn't covering the whole Parent when the List isn't fully populated.
The Problem is the scrolling behaviour of the ListView, I can only browse in the small piece of window the ListView is initially loaded in.
(4 Entries or more do occupy the entire Parent, with less entries the problem happens)
Fragment:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#null"
/> </LinearLayout>
Main XML:
<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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:itemBackground="#color/bgBottomNavigation"
app:itemIconTint="#android:color/white"
app:itemTextColor="#android:color/white"
app:menu="#menu/navigation" />
</android.support.design.widget.CoordinatorLayout>
The ListView gets populated via Volley + JSON with an Adapter for the ListView. Comment if you need the Code.
When I'm trying to put the ListViews height on "match_parent" the whole screen is occupied by the ListView, but it isn't scrollable anymore.
What can I do?
EDIT:
Coordinator Layout - This is the Code of the Frame Coordinator with the Bottom Navigation in it:
<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/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?android:attr/windowBackground"
app:itemBackground="#color/bgBottomNavigation"
app:itemIconTint="#android:color/white"
app:itemTextColor="#android:color/white"
app:menu="#menu/navigation" />
</android.support.design.widget.CoordinatorLayout>
You could set a minimum height attribute to your listView and adjust to what suits you.
Eg. to set it to 20dp, add android:minHeight="20dp" to your listView attributes.
Best solution would be to wrap all the contents of the CoordinatorLayout inside a layout you can control yourself, like a ConstraintLayout. In that case you would align the FrameLayout (and the fragments it handles) between your other components and everything would be scrollable and clickable. A mock of this solution would be:
<CoordinatorLayout>
<ConstraintLayout height="match_parent">
<BottomNavigation bottomToBottomOf="parent" />
<FrameLayout height="0dp"
topToTopOf="parent"
bottomToTopOf="bottomNavigation" />
</ConstraintLayout>
</CoordinatorLayout>
I have a view which contains a top view (it's a mapview but it's not implemented yet) and a listview below it.
What I'm trying to do is to make the top of listview to be overlay the bottom of the top view a little bit. Here is something similar to what I'm trying to achieve :
(without the tab headers and the image will be the mapview)
I'm not sure how I can achieve that, here is what I have so far:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#android:color/holo_red_dark">
</View>
<com.hmm.widgets.CustomListView
android:id="#+id/runners_list"
android:background="#android:color/darker_gray"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:dividerHeight="10dp"
android:divider="#android:color/darker_gray">
</com.hmm.widgets.CustomListView>
</RelativeLayout>
I've tried negative margin which didn't work. I'm not sure how can I achieve something similar. Should I be using FrameLayout?
You can use LinearLayout in your case and design the layout like this. This is a trick of setting a negative layout_marginTop to your custom ListView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<View
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#android:color/holo_red_dark">
</View>
<com.hmm.widgets.CustomListView
android:id="#+id/runners_list"
android:background="#android:color/darker_gray"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="#dimen/activity_vertical_margin"
android:layout_marginRight="#dimen/activity_vertical_margin"
android:dividerHeight="10dp"
android:layout_marginTop="-40dp"
android:divider="#android:color/darker_gray">
</com.hmm.widgets.CustomListView>
</LinearLayout>
Complementing Reaz's answer, you can do it with RelativeLayout too without using negative margins (which are a bit controversial).
Note the last four attributes in the CustomListView: you constraint the height with alignParent*, set a dummy height which will be discarded, and offset the view from the top with a margin. The "negative offset" will be 250dp - 200dp = 50 dp.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#android:color/holo_red_dark">
</View>
<com.hmm.widgets.CustomListView
android:id="#+id/runners_list"
android:background="#android:color/darker_gray"
android:layout_width="match_parent"
android:dividerHeight="10dp"
android:divider="#android:color/darker_gray"
android:layout_height="0dp"
android:layout_marginTop="200dp"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true">
</com.hmm.widgets.CustomListView>
</RelativeLayout>
I have a CoordinatorLayout, in where a RecyclerView displays some CardViews, defined in an other layout. Under this scrollable view, i am trying to add a RelativeLayout, which inherits fields for text input, buttons for sending it, etc.
The problem: CoordinatorLayout seems to block the whole screen, although i told to wrap contents height. Nevertheless, RelativeLayout is added (tested it by setting Coordinator-height = 50dp), but off-screen. What is wrong here?
PS: I know how to solve it with android:layout_weight=xx. But thats not what i want to achieve, because it blocks my EditText to expand, if bigger texts are entered.
<RelativeLayout 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.support.design.widget.CoordinatorLayout
android:id="#+id/data_coordinator_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.design.widget.CoordinatorLayout>
<RelativeLayout
android:id="#+id/delete_data_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_below="#id/data_coordinator_layout">
<EditText/>
<Button/>
<Button/>
<Button/>
</RelativeLayout>
</RelativeLayout>
It's actually pretty simple. You need to align your Relative Layout (delete_data_layout) to bottom of your parent. Then you make the Coordinator layout above the Relative Layout. This causes, that Coordinator layout will always stay above the Relative Layout - even when the Edittext expands.
Here's the XML.
<RelativeLayout 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.support.design.widget.CoordinatorLayout
android:id="#+id/data_coordinator_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="#+id/delete_data_layout"> <---- Change here
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.CoordinatorLayout>
<RelativeLayout
android:id="#+id/delete_data_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"> <---- Change here
<EditText/>
<Button/>
<Button/>
<Button/>
</RelativeLayout>
</RelativeLayout>
I know this is a common question , but I am completely messed with those different examples and tutorials available on the web.
I have a horizontalScrollView where I add some view dynamically , and I want to set a guestureListener for swiping through the Views . Each view's with is equal to the width of the screen.
You can use the View Pager instead of the horizontalScrollView. http://developer.android.com/reference/android/support/v4/view/ViewPager.html
To keep the View pager at half the screen use something like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/White"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.5">
<android.support.v4.view.ViewPager
android:id="#+id/pagerPromo"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.viewpagerindicator.CirclePageIndicator
android:id="#+id/indicatorPromo"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="5dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1.0"
android:orientation="vertical">
This View Pager has a circle indicator at the bottom but you can remove that if you like. Just play around with the weights and see what works best for you.