Show multiple layout step by step in a Persistent Bottom Sheet - android

I want to change layouts dynamically in a persistent bottom sheet, not the modal one.
I have 4 layouts and have to show those layouts in the bottom sheet step by step.
Is it a good idea to use a fragment container in bottomsheet like the below one and add fragments in it one by one?
or I have to use a layout container and then add other layouts using addView and removeView.
The layouts have different heights so I want to adjust the bottomsheet height according to the height of every layout when they show.
I checked some examples using Modal bottom sheet and fragments. But I need it in a persistent one like google maps. So I am not sure if fragments will cause any problems in a persistent sheet and if there are better and simple solutions than fragments.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:orientation="vertical"
android:padding="12dp"
app:behavior_hideable="false"
app:behavior_peekHeight="100dp"
app:layout_insetEdge="bottom"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<View
android:layout_width="40dp"
android:layout_height="4dp"
android:background="#drawable/circle_background"
android:layout_gravity="center_horizontal"/>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/bottomSheetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginTop="15dp"/>
</FrameLayout>

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 .

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>

stacking two android fragments vertically

I am designing a UI for a calculator, but I want to use different fragments for different parts of the UI displayed simultaneously. However I want stack fragments vertically in a relative layout.
Yet, I want the fragment1 size be set by the size of the controls and not hard-code some height. That way I can easily change the controls of fragment1 without worrying about its total height.
I tried a relative layout but I can't get fragment2 to be displayed below fragment1. Here's what I have tried
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/side_panel"
android:layout_width="match_parent"
<!--this sort of sucks (don't want hadcode 100dp, I want the controls I put in here to resize this automatically.-->
android:layout_height="100dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
class="com.guitarv.www.ndigitcalc.SidePanelFragment">
</fragment>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/main_panel"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_below="#+id/side_panel"
class="com.guitarv.www.ndigitcalc.MainPanelFragment">
</fragment>
</RelativeLayout>
any suggestions in how to make this work?
thx!

CardView Scroll behavior when keyboard is up

Our app's main content is a RecylerView of CardView's. For signup we require more than just a username/password to create an account so we decided to make the signup flow out of CardView's to match the user experience once they sign up.
To do that I have a single Activity that animates fragments in from the bottom and existing fragments out the top to emulate scrolling. This fake scrolling occurs when the user enters data and hits next to advance. This works pretty well except for one case. When we have a EditText for input the keyboard comes up and covers the 'next' button on the bottom of the screen.
In our user testing we've noticed a high percentage of users trying to scroll the card up to get to the next button instead of dismissing the keyboard.
I've spent a lot of time unsuccessfully trying to get the CardView to scroll up to reveal the button and I'm out of ideas and looking for new ones.
The signup Activity layout only contains a FrameLayout that I load Fragments into. Each fragment that gets loaded has a CardView for the root layout.
In the manifest I have set the activity's windowsSoftInputMode to adjustResize, adjustPan with little success.
activity_signup.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/signUpContent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
simplified fragment_enter_code.xml
<android.support.v7.widget.CardView
style="#style/CardViewStyle.SignUp"
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="wrap_content"
app:cardCornerRadius="25dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true"
app:contentPadding="8dp">
<EditText
android:id="#+id/codeEditText"
style="#style/HintedEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Code"
android:inputType="text"/>
<Button
style="#style/NextButton"
android:id="#+id/nextButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="#string/next"/>
</android.support.v7.widget.CardView>
When I tried putting the CardView in a ScrollView the cardview layout (with fillViewport true), I get a scrollbar but the card doesn't scroll and the cardview layout gets messed up.
Does anyone know the windowSoftInputMode's well enough to point me in the right direction? Or is the CardView just not going to scroll outside of a Container that is design to hold them?
It feels like the solution to this is in manipulating the activity's view not the fragments.
I ended up creating a new app to just play around with this issue and noticed that if I had a layout that didn't contain a CardView whose root layout was a ScrollView it didn't scroll unless the activities windowSoftInputMode is set to adjustResize and then it will scroll.
I then made a layout with a <ScrollView><CardView><content...></CardView></ScrollView> and the size of the CardView was always the default row size for a card and wouldn't match_parent. I solved that with fillViewPort="true" on the ScrollView but when the keyboard came up it wouldn't scroll.
Turns out the secret sauce was to put a FrameLayout (or anyother layout) in between the CardView and the ScrollView.
You still have to account for the resize of the Layout to prevent your view elements not stacking over each other but Once you do that you now get the view above the soft keyboard to scroll and the ability to reach the rest of the UI with a CardView.
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fillViewport="true">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardCornerRadius="35dp"
app:cardElevation="2dp"
app:cardUseCompatPadding="true"
app:contentPadding="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="#drawable/common_ic_googleplayservices"/>
<EditText
android:id="#+id/input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_below="#id/image"
android:hint="Input"
android:inputType="text"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/input"
android:orientation="vertical"
android:gravity="bottom|center_horizontal">
<Button
android:id="#+id/nextButton"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:enabled="false"
android:text="Next"/>
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
</ScrollView>

How to arrange multiple android fragments with nested FrameLayouts?

I'd like to display a simple landscape layout with one list fragment on the left half of the screen and two vertically aligned fragments on the right. Showing all three fragments horizontally works fine, but my layout below shows only the list fragment and not the two others inside the vertical LinearLayout on the right. What am I doing wrong with my layout parameters?
<?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="horizontal">
<fragment class="com.copperykeenclaws.gameplanner.TeamListFragment"
android:id="#+id/team_list_fragment"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_weight="1"
android:layout_width="0px"
android:layout_height="wrap_content">
</fragment>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout android:id="#+id/team_details_frame"
android:layout_width="0px"
android:layout_height="wrap_content"/>
<FrameLayout android:id="#+id/team_players_frame"
android:layout_width="0px"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>
The FrameLayouts get replaced programmatically in FragmentTransactions, which works fine in the all-horizontal layout.
Both team_details_frame and team_players_frame have widths of 0px, so they'll won't show. Either give them a layout_weight attribute (although nested layout_weights are discouraged, I doubt there will be much of a performance hit in your case) or set them to wrap_content or match_parent.

Categories

Resources