BottomSheetBehavior padding - android

I have such kind of fragment layout.
<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:background="#color/colorBackgroundBlack">
<MyCustomView
android:id="#+id/vBottomSlider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />
</android.support.design.widget.CoordinatorLayout>
For my vBottomSlider I create a BottomSheetBehavior instance:
val bh = BottomSheetBehavior.from(vBottomSlider)
bh.isHideable = false
bh.peekHeight = 50.dpToPx
bh.setBottomSheetCallback(mBottomCallback)
That's all inside the fragment.
My main activity layout looks like:
<android.support.constraint.ConstraintLayout
android:id="#+id/vMainConstraint"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fContent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="#+id/vNavigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>
For my fContent i set bottom padding as vNavigation height. When i scroll down my vBottomSlider, i hide vNavigation by changing its translationY, and set padding for my fContent (by taking onSlide event from BottomSheetBehavior.BottomSheetCallback).
Sliding with finger completely, works fine.
But when i fling or set EXPANDED or COLLAPSED state programmatically for my BottomSheetBehavior instance its not get scrolled completely. Here is always some space (it seems to be height of my vNavigation).

I've managed to resolve this by editing the source of BottomSheetBehavior.
My solution is little hacky. Send e-mail if you need edited class.

Related

remove default margin bottom from Toolbar

In my application I use the android.support.v7.widget.Toolbar for the toolbar.
Here is 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.todo.app.MainActivity"
style="#style/MainActivityBg">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="#style/AppTheme.AppBarOverlay"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
style="#style/AppTheme.ActionBar"/>
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_main"/>
and
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/activity_main"
tools:context="com.todo.app.MainActivity"
android:layout_marginTop="5dp"> <!-- for adding some space between the toolbar and the rest, and this is the cause of the problem! -->
<android.support.v7.widget.RecyclerView
android:id="#+id/task_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I try to add some space between the toolbar and the rest of the view. To do that I added 5dp in marginTop to the layout which is right under the view. And this causes this problem:
While I scrolling the view there is some space remaining under the toolbar.
In my style files xml, there is no style for margin or padding.
How I can adding some space between toolbar and the rest without trigger this problem (when I scrolling the view)?
Reason
Based on the xml files, it seems to me that:
<android.support.constraint.ConstraintLayout
...
android:layout_marginTop="5dp">
is the reason for cropping RecyclerView content.
When you set the layout_marginTop between the AppBarLayout and the upper edge of ConstraintLayout appears a 5dp high empty space.
You can confirm that by turning on one of the Android options for developers: Show Layout Bounds.
Solution
For the effect which you want to achieve try to remove android:layout_marginTop and set android:paddingTop for the RecyclerView but also set android:clipToPadding to false.
Check the gif in this SO answer.
<android.support.v7.widget.RecyclerView
android:id="#+id/task_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="5dp"
android:clipToPadding="false" />
This will allow you to add the desired space at the beginning of scrollable content but prevent cropping the items.
If the 5dp top margin isn't the problem, it may be the toolbar elevation, try to change 4dp to something much higher and check if changes your problem. Can you try same with margin top? Also a negetive margin sometimes work. Put a negetive margin on button of the toolbar and check.

Expand/Fold a Layout when user swipes

In an Android project, I have an Activity that contains (from top to bottom) a header, a RecyclerView and a RelativeLayout.
Code sample :
<android.support.design.widget.CoordinatorLayout ...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
...
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
This is the behaviour I want : the RelativeLayout is "folded" by default, i.e. under the RecyclerView. When the user swipes up, the RelativeLayout expands to use the whole screen, and folded again when swipes down.
What is the right way to do it ? As I want the RelativeLayout to be BELOW the RecyclerView when folded, and OVER it when expanded. I tried setting the dependencies between elements dynamically but couldn't manage to do so.
Thanks for any help or advice on how to organize the activity to get such a behaviour.
EDIT
This is the XML structure :
<CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</AppBarLayout>
<RecyclerView
android:id="#+id/top_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/app_bar"
android:layout_above="#+id/relativelayout_footer" />
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_alignParentBottom="true">
<TextView ...>
<RecyclerView
android:id="#+id/included_list"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
</CoordinatorLayout>
And the listener :
top_list.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
app_bar.setVisibility(playlistOpened ? View.VISIBLE : View.GONE);
included_list.setVisibility(playlistOpened ? View.GONE : View.VISIBLE);
Transition cb = new ChangeBounds();
cb.setDuration(1000);
TransitionManager.beginDelayedTransition(slider, cb);
playlistOpened = ! playlistOpened;
As you see, I switch the visibility of the elements in order to reorganise the view. When the included_list is set to VISIBLE, it pushes up the TextView.
The only problem is that the top_list and the app_bar disappear before being covered by the RelativeLayout. I tried adding a Listener to the Transition and do these when the transition ends, but it doesn't work (I guess because they're not set to GONE at the beginning, so the RelativeLayout can't move up). Any idea of how to do so ? Maybe I should open another question for it ?
Okay, a final attempt. I am back to RelativeLayout and added another one around the RecyclerView to fix its scrolling problem. However, transitions get tricky (and the listener complicated) then. In order to prevent the RecyclerView from popping away before the RelativeLayout with the TextView inside fully covers the latter, I had to include a fading transition to the RecyclerView, too. Hope this suits you.
XML:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/rlwithrecyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/rlwithtextview"
android:layout_alignParentTop="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/rlwithtextview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:layout_width="match_parent"
android:layout_height="400dp"
android:id="#+id/textview"
android:text="Just a test" />
</RelativeLayout>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
onClick():
#Override
public void onClick(View v) {
RelativeLayout rlWithRecyclerView = findViewById(R.id.rlwithrecyclerview);
RelativeLayout.LayoutParams layoutParamsRlWithRecyclerView;
RelativeLayout rlWithTextView = findViewById(R.id.rlwithtextview);
RelativeLayout.LayoutParams layoutParamsRlWithTextView;
if (rlWithTextView.getLayoutParams().height == MATCH_PARENT) {
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ALIGN_PARENT_TOP);
layoutParamsRlWithRecyclerView.addRule(RelativeLayout.ABOVE, R.id.rlwithtextview);
} else {
layoutParamsRlWithRecyclerView = new RelativeLayout.LayoutParams(MATCH_PARENT, 0);
layoutParamsRlWithTextView = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
}
layoutParamsRlWithTextView.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
Transition changeBounds = new AutoTransition();
changeBounds.setDuration(500);
TransitionManager.beginDelayedTransition(rlWithRecyclerView, changeBounds);
TransitionManager.beginDelayedTransition(rlWithTextView, changeBounds);
rlWithRecyclerView.setLayoutParams(layoutParamsRlWithRecyclerView);
rlWithTextView.setLayoutParams(layoutParamsRlWithTextView);
}
Although I got credit for the two other answers, I will eventually delete them, since they don't solve the problem.

Android bottom toolbar disappears when fragment fills screen

I'm working on an android app and am using a toolbar at the top of the screen and a navigation bar at the bottom of the screen. I'm using a single activity to create the top and bottom toolbars and fragments to change the content between the toolbars. However, when the contents in the fragment go beyond the size of the screen, the bottom bar disappears.
Here is my home activity 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"
android:id="#+id/activity_home"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.rentables.testcenter.HomeActivity">
<include
android:id="#+id/toolbar_main"
layout="#layout/toolbar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<fragment android:name="com.rentables.testcenter.HomeFragment"
android:id="#+id/fragment_place"
android:layout_weight="0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:layout="#layout/fragment_home" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="bottom">
<include
android:id="#+id/toolbar_navigate"
layout="#layout/toolbar_navigate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|bottom"/>
</LinearLayout>
</LinearLayout>
Im guessing it's because of the inner linear layout I have, but I wasn't sure how else to get the nav bar to stay static at the bottom. Any help would be awesome. Thanks
Figured it out. I just changed the whole thing to a relative layout, got rid of the inner linear layout, and instead of gravity I used alignParentBottom="true".

Navigation Drawer Layout overlapping with frame layout

whenever i open my navigation drawer frame layout contents are getting shown in background i even tried setting the frame's color white
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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:id="#+id/drawer_layout"
tools:context="com.example.sumanravi.knowmycity.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/content_layout"
android:background="#color/white">
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:orientation="vertical">
<ListView
android:layout_width="200dp"
android:layout_height="match_parent"
android:id="#+id/navList"
android:choiceMode="singleChoice">
</ListView>
</LinearLayout>
If what you want to do is to hide the contents of a layout, you can:
Hide the whole layout (setting visibility to View.GONE or View.VISIBLE)
Change the alpha (setting alpha on the layout itself)
Remove all of the layout's children (please don't use this method, it's stupidly slow)
Containing views will always have their parent's background drawn underneath them. Another fun way to hide the content is to use the drawer listener: https://developer.android.com/reference/android/support/v4/widget/DrawerLayout.DrawerListener.html#onDrawerSlide(android.view.View, float) - look for onDrawerSlide(View, float) method and (for example) change the View's alpha as you go.
Another thing you could do with FrameLayouts is to set the foreground: set forground color in framelayout in android programatically
But generally, content under navigation drawers is always (at least partially) visible. If you're trying to hide it, you're probably not following the guide.

How can I add a shadow to bottom sheet view?

As of now, with the official bottom sheet component from the Android design library implemented the top edge doesn't show a shadow. But for what I've seen in various mockups and in the Material Design specs, the bottom sheet include a discrete shadow of some sort.
I think the shadow would help distant the bottom sheet from the main layout, especially if there's a peek value set and/or the bottom sheet is always visible. Otherwise it just will blend together with the main layout and its items.
I've tried both ViewCompat.setElevation(bottomSheet, 5); and setting android:elevation="5dp" to the view in the XML, without success.
I know that a shadow shape doesn't have the same appearance as an elevation - but at least give it a try. The trick is to use app:layout_anchor to clip the shadow to the bottom sheet.
activity_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:layout_width="match_parent"
android:layout_height="match_parent">
<MapView
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<View
android:id="#+id/shadow"
android:layout_width="match_parent"
android:layout_height="16dp"
android:background="#drawable/shape_gradient_top_shadow"
app:layout_anchor="#id/bottom_sheet" />
<FrameLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="200dp"
android:clipToPadding="false"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />
</android.support.design.widget.CoordinatorLayout>
shape_gradient_top_shadow.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="#android:color/transparent"
android:startColor="#64000000"/>
</shape>
Looks like this:
EDIT
Get an even better result with a custom ShadowView:
Post from Roman Nurik on this topic: https://plus.google.com/+RomanNurik/posts/2QvHVFWrHZf
Gist of the ShadowView based on Roman Nurik's solution: https://gist.github.com/MariusBoepple/bf869e02541cd4750550e88fa07b5ddd
Then you can do the following:
<ShadowView
android:id="#+id/shadow"
android:layout_width="match_parent"
android:layout_height="16dp"
android:gravity="bottom"
app:layout_anchor="#id/bottom_sheet" />
For API Level 21 and higher, set the following in the parent view. You can also try in the rootview of the bottomsheet (I have not tried it in the root view)
android:background="#android:color/white"
android:elevation="16dp"
If no background then can use
android:outlineProvider="bounds"
For example, I have my sheet inside a nested scroll view
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:elevation="16dp"
android:outlineProvider="bounds"
>
<include layout="#layout/bottomsheet_1" />
</android.support.v4.widget.NestedScrollView>
The trick is to use a CardView as parent and set the elevation in the CardView
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:background="#fff"
android:clickable="true"
android:focusable="true"
app:behavior_hideable="true"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:layout_height="140dp"
app:cardElevation="8sp"
card_view:cardCornerRadius="0dp">
<!--The content of your Bottom sheet-->
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
.
.
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
EDIT
This technique is not the best solution if you are supporting Kitkat and below. It's due to the extra margin added by the Cardview.
I think this will help you
first create bottom sheet like bellow then include in your main activity
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="56dp"
android:layout_marginTop="0.5dp" // this margin depend on shadow area
android:background="set you color"
android:elevation="20dp" // chose your custom elevation
app:layout_behavior="#string/bottom_sheet_behavior">
<LinearLayout
android:layout_marginTop="1dp" // this margin depend on max elevation
android:layout_width="match_parent"
android:layout_height="200dp">
</LinearLayout>
</LinearLayout>

Categories

Resources