B4A Library [B4X] [XUI] AS Draggable Bottom Card

This is my 2k'th post on this Forum and i want to share a nice library with you i made some months ago.
It was not easy to create this library, it took many hours of testing and programming to make the user experience as good as possible.

If you want to support me, then you can do this here or with a coffee. Thanks :)

This lib. is only for B4I and B4A.
B4J is not tested and i currently dont want to support it
B4J is now supported


Features
  • cross-platform compatible
  • easy to use
  • use your own header and body layout
  • 2 states - half expanded and full expanded
  • Events
  • and more...
Some design inspiration:
Screenshot_20200814-175011.jpg

Screenshot_20200814-175140.jpg
ezgif.com-resize.gif
Screenshot_20200426-182000.jpg
Screenshot_20200308-221644.jpg
bottom card.PNG

20-04-04-13-55-05.gif
com.stoltex.asdraggablebottomc_Screenshot_2021.02.23_11.49.59.png
1614077514655.png
TvAP4JLxzvCPBxjKZn2xMLq1B3HnIQkPQq6VYdMPdCEa8r9cfF.jpeg



ASDraggableBottomCard
Author: Alexander Stolte
Version: 1.05

  • ASDraggableBottomCard
    • Events:
      • Close
      • Closed
      • Open
      • Opened
      • VisibleBodyHeightChanged (height As Double)
    • Fields:
      • g_hide_duration As Int
      • g_show_duration As Int
    • Functions:
      • Base_Resize (Width As Double, Height As Double) As String
      • BodyPanel As B4XView
        gets the body panel - Load your body layout
      • Class_Globals As String
      • Create (Parent As B4XView, first_height As Float, second_height As Float, header_height As Float, width As Float, orientation As Int) As String
        Base type must be Object
      • ExpandFull As String
        expand the view full - second height + header height
      • ExpandHalf As String
        expand the view in half mode - first height + header height
      • getCardBase As B4XView
        gets the card base - the main panel that hold the body- and header-panel
      • getDarkPanelAlpha As Int
      • getFirstHeight As Float
      • getHeaderHeight As Float
        gets the header height
      • getIsDraggable As Boolean
      • getIsOpen As Boolean
        Returns True if the view is expanded/open
      • getIsOpenFull As Boolean
        Returns True if the view is full expanded
      • getIsOpenHalf As Boolean
        Returns True if the view is half expanded
      • getSecondHeight As Float
      • HeaderPanel As B4XView
        gets the header panel - Load your header layout
      • Hide (ignore_event As Boolean)
        hides/close the view
      • Initialize (Callback As Object, EventName As String) As String
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • Orientation_LEFT As Int
      • Orientation_MIDDLE As Int
      • Orientation_RIGHT As Int
      • setCornerRadius_Header (radius As Float) As String
        sets the corner radius of the header
      • setDarkPanelAlpha (alpha As Int) As String
      • setFirstHeight (height As Float) As String
        sets or gets the first height - body height
        The Event VisibleBodyHeightChanged is triggered if the menu is currently open at the first height
      • setIsDraggable (draggable As Boolean) As String
        set it to false to disable touch gestures on header panel
      • setSecondHeight (height As Float) As String
        sets or gets the second height - body height
        The Event VisibleBodyHeightChanged is triggered if the menu is currently open at the second height
      • Show (ignore_event As Boolean) As String
    • Properties:
      • CardBase As B4XView [read only]
        gets the card base - the main panel that hold the body- and header-panel
      • CornerRadius_Header
        sets the corner radius of the header
      • DarkPanelAlpha As Int
      • FirstHeight As Float
        sets or gets the first height - body height
        The Event VisibleBodyHeightChanged is triggered if the menu is currently open at the first height
      • HeaderHeight As Float [read only]
        gets the header height
      • IsDraggable As Boolean
        set it to false to disable touch gestures on header panel
      • IsOpen As Boolean [read only]
        Returns True if the view is expanded/open
      • IsOpenFull As Boolean [read only]
        Returns True if the view is full expanded
      • IsOpenHalf As Boolean [read only]
        Returns True if the view is half expanded
      • SecondHeight As Float
        sets or gets the second height - body height
        The Event VisibleBodyHeightChanged is triggered if the menu is currently open at the second height
Changelog
  • 1.00
    • Release
  • 1.01
    • Various bug fixes and improvements
    • The menu no longer closes when the last swipe went up, so it is now possible for the user to cancel a full close
  • 1.02
    • Add CornerRadius_Header - sets the CornerRadius of the header
      • dont use asdbc_main.HeaderPanel.Height if your set the corner radius, the returning height is not the display height
      • use HeaderHeight instead
    • Add HeaderHeight - gets the displayed header height
    • Supports now B4J
  • 1.03
    • Add set FirstHeight - sets the FirstHeight - The Event VisibleBodyHeightChanged is triggered if the menu is currently open at the first height
    • Add set SecondHeight - sets the SecondHeight - The Event VisibleBodyHeightChanged is triggered if the menu is currently open at the second height
    • Important BugFixes!
  • 1.04
    • BugFix on Drag with finger - much more better experience now!
  • 1.05
    • Add get IsOpenHalf - Returns True if the view is half expanded
    • Add get IsOpenFull - Returns True if the view is full expanded
    • Add IsDraggable - set it to false to disable touch gestures on header
    • Add some property descriptions
  • 1.06
    • B4I and B4J - Body can now be dragged too
  • 1.07
    • BugFixes
    • Significant handling improvements when working with 2 heights
  • 1.08
    • Add get DarkPanel
    • Add DarkPanelClickable - If false then does the menu not close when you click on the dark area
      • Default: True
  • 1.09
    • Add UserCanClose - If False then the user can expand the menu, but not close
  • 1.10
    • BugFixes
    • Add set and get BodyDrag - Call it before "Create"
      • If True then you can drag the body too
      • Not working if a list is in the body
  • 1.11
    • Add BodyDragPanel
  • 1.12
    • B4I only remove GestureRecognizer
  • 1.13
    • BugFix
Have Fun :)
 

Attachments

  • AS DraggableBottomCard Example.zip
    16.9 KB · Views: 1,101
  • ASDraggableBottomCard.b4xlib
    4.3 KB · Views: 234
Last edited:

lucasheer

Active Member
Licensed User
Longtime User
Hello!

Not sure if it is alright to post on this thread, but love this library!

However- In B4A, any panels in the first LoadLayout are shown over the DraggableBottomCard. Even though the Draggable bottom card was initialized and created after LoadLayout?

I tried:
B4X:
asdbc_main.BodyPanel.BringToFront
asdbc_main.Headerpanel.BringToFront
asdbc_main.DarkPanel.BringToFront
asdbc_main.BodyPanel.Parent.BringToFront

Thank you!


Edit- Figured it out, it was because of panel elevation on my form controls. Here was my fix:
B4X:
Dim pp As Panel = asdbc_main.BodyPanel.Parent
pp.Elevation = 1dip
 
Last edited:

b4x-de

Active Member
Licensed User
Longtime User
I use the DraggableBottomCard in the immersive mode of an Acticvity that fills the entire screen. On devices with a notch, the problem arises that when the card is fully opened (ExpandFull), the notch overlaps the header panel. Therefore I would like to be able to adjust the height of the header panel to react to a notch. I can determine the height of the notch myself. But I can't then adjust the height of the header panel. Would it please be possible to implement a setHeaderHeight(Height As Float) in addition to the getHeaderHeight()? Thanks a lot!
 

b4x-de

Active Member
Licensed User
Longtime User
Thank you, but it is not the FirstHeight or SecondHeight I'm asking for but the HeaderHeight.
 

b4x-de

Active Member
Licensed User
Longtime User
The notch height of a device only affects the HeaderHeigt when the card is fully opened in Immersive Mode. Therefore, I want to adjust the HeaderHeight when the card is fully opened and the device has a notch. In all other cases the HeaderHeight will not be adjusted.


Currently, I can only have the same HeaderHeight for both sizes. There is no way to change it.
 

Attachments

  • IMG_20230517_124846.png
    IMG_20230517_124846.png
    495.5 KB · Views: 83
  • Screenshot_20230517_124759.jpg
    Screenshot_20230517_124759.jpg
    60.4 KB · Views: 74

Alexander Stolte

Expert
Licensed User
Longtime User
Changing the height of the header is not provided. I have already spent 20 minutes implementing it, but I would have to make deep changes. So it will not be implemented for now.

I looked at your images, I recommend you to change the height of the body, everything else would look strange. Just take the height of the activity, subtract the height of the notch, then you have the perfect height.
 

b4x-de

Active Member
Licensed User
Longtime User
Far from beeing perfect, but it seems to work in B4A:

B4X:
Public Sub setHeaderHeight(pfltHeight As Float)
    Dim fltHeightDiff As Float
  
    fltHeightDiff = pfltHeight - g_header_height
  
    If fltHeightDiff = 0 Then
        Return
    End If
    g_header_height = pfltHeight
    If expand_state = 1 Then
        xpnl_card_header.SetLayoutAnimated(0,0,0,g_width,g_header_height)
        xpnl_card_body.SetLayoutAnimated(0,0,g_header_height,g_width,g_first_height + g_header_height)
    Else
        xpnl_card_header.SetLayoutAnimated(0,0,0,g_width,g_header_height)
        xpnl_card_body.SetLayoutAnimated(0,0,g_header_height,g_width,g_second_height)
    End If
    xpnl_card_header.Height = g_header_height * 2
    VisibleBodyHeightChanged
End Sub
 
Last edited:

Kope

Active Member
Licensed User
This class works great on Android. Thank you Alexander!

Currently I’m struggling with it B4i. I added a reference to GestureRecognizer found here. Now it compiles without any error. But the menu does not show up at all. Probably I’m doing some wrong when initializing the card like this:

B4X:
Private Sub Application_Start (Nav As NavigationController)
    NavControl = Nav
    MainPage.Initialize("MainPage")
    MainPage.RootPanel.LoadLayout("frm_main")
    NavControl.ShowPage(MainPage)
  
    asdbc_main.Initialize(Me,"asdbc_main")
    asdbc_main.Create(MainPage.RootPanel,MainPage.RootPanel.Height/2,MainPage.RootPanel.Height - 60dip,50dip,MainPage.RootPanel.Width - 20dip,asdbc_main.Orientation_MIDDLE)
    asdbc_main.HeaderPanel.LoadLayout("frm_header")
    asdbc_main.BodyPanel.LoadLayout("frm_body")
  
End Sub

I provided a simple B4i Example that can be used to test this issue. Any help is appreciated!

Thanks, Thomas
am currently having same issue since am not using b4xpages

please help us out
 
Top