iOS Question Common layout in multiple pages in tab bar controller

Rory Mapstone

Member
Licensed User
Longtime User
I have a questoin regarding the best way to keep a common layout properties the same between all pages inside a tab bar controller.

The layout PostAs needs to be the same in mapPage and listPage, and needs to stay synced between them. In the code below I make a copy of pnlContainerPostAs with pnlContainerPostAsListPage for the list page and then I plan to copy the views/properties when the mapPage/ListPage Appear event is fired. Is this the best way to handle it?

B4X:
'Code module

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Private App As Application
    Private mapPage, listPage As Page
    Dim map As GoogleMap
    Private pnlView, pnlMap, pnlClv As Panel
    Private lblTitle As Label
    Private pnlContainerPostAs, pnlContainerPostAsListPage As Panel
    Private clv_postAs, clv_postAsListPage As CustomListView
    Private btnPostAsCancel As Button
    Private lblPostAs As Label
End Sub
   
Sub show
   
    If Global.PageHeight = -1 Then Global.PageHeight = 100%y
    If Global.PageWidth = -1 Then Global.PageWidth = 100%x
    mapPage.Initialize("mapPage")
    listPage.Initialize("listPage")
    listPage.RootPanel.LoadLayout("logeneral")
    listPage.RootPanel.LoadLayout("lomap")
    pnlClv = pnlView
    pnlClv.LoadLayout("loclv")
    listPage.RootPanel.LoadLayout("loPostAs")
    pnlContainerPostAsListPage = pnlContainerPostAs
    lblTitle.Text = "List"
    lblPostAs.Text = "Explore by"

    mapPage.RootPanel.LoadLayout("logeneral")
    mapPage.RootPanel.LoadLayout("lomap")
    pnlMap = pnlView
    pnlMap.LoadLayout("lomap2")
    mapPage.RootPanel.LoadLayout("loPostAs")
    lblTitle.Text = "Map"
    lblPostAs.Text = "Explore by"
   
    Global.SetPageTitle(mapPage, "Map View")
    Global.SetPageTitle(listPage, "List View")
    Global.AddTabBarController("tc",App,Array(mapPage, listPage), 0)
    Global.resetDefaultHeights

    'Global.hd.ProgressDialogShow("Loading...")
    getDetails
   
    map.Initialize("map","AIzaSyCaLtZdyg3DCQ8OuvdO7pIA7m9TSaKYyHk")
    pnlMap.AddView(map, 0,0,pnlMap.width,pnlMap.Height)
    map.MyLocationEnabled = True
    map.GetUiSettings.CompassEnabled = True
    map.GetUiSettings.MyLocationButtonEnabled = True

End Sub

Sub listPage_Appear
   
If Global.TabController.SelectedIndex == 1 Then
        For Each v As View In pnlContainerPostAs.GetAllViewsRecursive
            pnlContainerPostAsListPage.AddView(v, v.Left, v.Top,v.Width, v.Height)
        Next
    End If
End Sub

Sub mapPage_Appear
'Vise versa of listpage
For Each v As View In pnlContainerPostAsListPage.GetAllViewsRecursive
            pnlContainerPostAs.AddView(v, v.Left, v.Top,v.Width, v.Height)
        Next
    End If
End Sub

Sub getDetails
   
End Sub

Sub btnBack_Click
    Global.doBack(0)
End Sub

Sub ivCategory_Click
    If Global.TabController.SelectedIndex = 0 Then
        Global.showpostaspnl(pnlContainerPostAs, clv_postAs, btnPostAsCancel)
    Else
        Global.showpostaspnl(pnlContainerPostAsListPage, clv_postAsListPage, btnPostAsCancel)
    End If
End Sub


Sub btnPostAsCancel_Click
   
    If Global.TabController.SelectedIndex = 0 Then
        Global.hidepostaspnl(pnlContainerPostAs)
    Else
        Global.hidepostaspnl(pnlContainerPostAsListPage)
    End If
End Sub
 

Rory Mapstone

Member
Licensed User
Longtime User
1. Implement it in a class.
2. In B4i you can move views / panels between pages. So there is no problem to just move the complete layout to a different page.

Thanks for the suggestion, this is what I have tried and it is behaving better but do I really need to create two objects here? :

B4X:
'classPostAs
Sub Class_Globals
    Private pnlContainerPostAs As Panel
    Private clv_postAs As CustomListView
    Private lblPostAs As Label
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize(page As Page, title As String)
    page.RootPanel.LoadLayout("loPostAs")
    lblPostAs.Text = title
End Sub

public Sub populateClv(data As Map)
'populate clv here
End Sub

'copy views
public Sub setPanel(p As Panel)
    pnlContainerPostAs.RemoveAllViews
    For Each v As View In p.GetAllViewsRecursive
        pnlContainerPostAs.AddView(v, v.Left, v.Top,v.Width, v.Height)
    Next
End Sub

'basically returns the entire layout, pnlContainerPostAs contains all the views
public Sub getView As Panel
    Return pnlContainerPostAs
End Sub

public Sub showpostaspnl
    pnlContainerPostAs.Visible = True
    pnlContainerPostAs.SetLayoutAnimated(Constants.animationTime,1, 0, 0, Global.PageWidth, Global.PageHeight)
    pnlContainerPostAs.BringToFront
End Sub

public Sub hidepostaspnl
    pnlContainerPostAs.Visible = False
    pnlContainerPostAs.SetLayoutAnimated(Constants.animationTime, 1, -Global.PageWidth, 0, 0, 0)
End Sub


Sub btnPostAsCancel_Click
    hidepostaspnl
End Sub

Implementation:
B4X:
'Code module
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Private App As Application
    Private mapPage, listPage As Page
    Dim map As GoogleMap
    Private pnlView, pnlMap, pnlClv As Panel
    Private lblTitle As Label
    Private mapPostAs, ListPostAs As classPostAs
End Sub
   
Sub show
    If Global.PageHeight = -1 Then Global.PageHeight = 100%y
    If Global.PageWidth = -1 Then Global.PageWidth = 100%x
    mapPage.Initialize("mapPage")
    listPage.Initialize("listPage")
    listPage.RootPanel.LoadLayout("logeneral")
    listPage.RootPanel.LoadLayout("lomap")
    pnlClv = pnlView
    pnlClv.LoadLayout("loclv")
   
    'create two objects of postAs layout in here, not sure if it is necessary?
    mapPostAs.Initialize(mapPage, "Explore by")
    ListPostAs.Initialize(listPage, "Explore by")
   
    lblTitle.Text = "List"
    mapPage.RootPanel.LoadLayout("logeneral")
    mapPage.RootPanel.LoadLayout("lomap")
    pnlMap = pnlView
    pnlMap.LoadLayout("lomap2")
    lblTitle.Text = "Map"
   
    'Set page details and tab bar details
    Global.SetPageTitle(mapPage, "Map View")
    Global.SetPageTitle(listPage, "List View")
    Global.AddTabBarController("tc",App,Array(mapPage, listPage), 0)
    Global.resetDefaultHeights
   
   
    'init map view
    map.Initialize("map","AIzaSyCaLtZdyg3DCQ8OuvdO7pIA7m9TSaKYyHk")
    pnlMap.AddView(map, 0,0,pnlMap.width,pnlMap.Height)
    map.MyLocationEnabled = True
    map.GetUiSettings.CompassEnabled = True
    map.GetUiSettings.MyLocationButtonEnabled = True
   
    'api to get data for map and list
    getDetails
End Sub

Sub listPage_Appear
    ListPostAs.setpanel(mapPostAs.getview)
End Sub

Sub mapPage_Appear
    mapPostAs.setpanel(ListPostAs.getview)
End Sub

Sub getDetails
   
End Sub

Sub btnBack_Click
    Global.doBack(0)
End Sub

Sub mmm_CameraChange (Position As CameraPosition)
    Log("test" & map.MyLocation)
'    Dim loc As LatLng
'    loc.Initialize()
'  
   
End Sub

'Sub gpsLocation_callback
'    Dim c As CameraPosition
'    c.Initialize(gpsSVC.Latitude, gpsSVC.Longitude , 10)
'    map.AnimateCamera(c)
'    Global.hd.ProgressDialogHide
'End Sub

Sub ivCategory_Click
    If Global.TabController.SelectedIndex = 0 Then
        mapPostAs.showpostaspnl
    Else
        ListPostAs.showpostaspnl
    End If
End Sub

Sub btnPostAsCancel_Click
    If Global.TabController.SelectedIndex = 0 Then
        mapPostAs.hidepostaspnl
    Else
        ListPostAs.hidepostaspnl
    End If
End Sub
 
Upvote 0

Rory Mapstone

Member
Licensed User
Longtime User
Which two objects?
Two objects of the classPostAs

B4X:
 mapPostAs.Initialize(mapPage, "Explore by")
 ListPostAs.Initialize(listPage, "Explore by")

I do this so I can set the views to be the same but I am not sure if there is a better way.
B4X:
Sub listPage_Appear
    ListPostAs.setpanel(mapPostAs.getview)
End Sub

Sub mapPage_Appear
    mapPostAs.setpanel(ListPostAs.getview)
End Sub

Is this what you were referring to when moving views from page to page?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
No.

1. Don't create the views every time you call show. See this example: https://www.b4x.com/android/forum/threads/multiple-pages-example.48170/#content
2. Never use %x / %y outside of the Resize event (or at least know that they will be incorrect).
3. Add all the views to a panel. When you want to show the layout you should check whether panel.Parent.IsInitialized. If it is then call panel.RemoveViewFromParent.
4. Add the panel to the new parent.

This way you will need need to worry about the state of each view.
 
Upvote 0

Rory Mapstone

Member
Licensed User
Longtime User
No.

1. Don't create the views every time you call show. See this example: https://www.b4x.com/android/forum/threads/multiple-pages-example.48170/#content
2. Never use %x / %y outside of the Resize event (or at least know that they will be incorrect).
3. Add all the views to a panel. When you want to show the layout you should check whether panel.Parent.IsInitialized. If it is then call panel.RemoveViewFromParent.
4. Add the panel to the new parent.

This way you will need need to worry about the state of each view.
Thanks Erel, I have changed it as follows. I think it is correct now:

B4X:
'Code module
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Private App As Application
    Private mapPage, listPage As Page
    Dim map As GoogleMap
    Private pnlView, pnlMap, pnlClv As Panel
    Private lblTitle As Label
    Private PostAs As classPostAs
    Private ivCategory As ImageView
End Sub
    
Sub show
    If mapPage.IsInitialized = False Then
        Global.resetDefaultHeights
        mapPage.Initialize("mapPage")
        listPage.Initialize("listPage")
        listPage.RootPanel.LoadLayout("logeneral")
        listPage.RootPanel.LoadLayout("lomap")
        pnlClv = pnlView
        pnlClv.LoadLayout("loclv")
        
        PostAs.Initialize(mapPage, "Explore by", ivCategory)
        
        lblTitle.Text = "List"
        mapPage.RootPanel.LoadLayout("logeneral")
        mapPage.RootPanel.LoadLayout("lomap")
        pnlMap = pnlView
        pnlMap.LoadLayout("lomap2")
        lblTitle.Text = "Map"
        
        'Set page details and tab bar details
        Global.SetPageTitle(mapPage, "Map View")
        Global.SetPageTitle(listPage, "List View")
        Global.AddTabBarController("tc",App,Array(mapPage, listPage), 0)
    End If
    
    'init map view
    map.Initialize("map","AIzaSyCaLtZdyg3DCQ8OuvdO7pIA7m9TSaKYyHk")
    pnlMap.AddView(map, 0,0,pnlMap.width,pnlMap.Height - 40dip)
    map.MyLocationEnabled = True
    map.GetUiSettings.CompassEnabled = True
    map.GetUiSettings.MyLocationButtonEnabled = True
    
    'api to get data for map and list
    getDetails
End Sub

Sub listPage_Appear
    If PostAs.getview.IsInitialized Then
        PostAs.getview.RemoveViewFromParent
        listPage.RootPanel.AddView(PostAs.getview, PostAs.getview.Left, PostAs.getview.Top, PostAs.getview.Width, PostAs.getview.Height)
    End If
    'ListPostAs.setpanel(mapPostAs.getview)
End Sub

Sub mapPage_Appear
    'mapPostAs.setpanel(ListPostAs.getview)
    If PostAs.getview.IsInitialized Then
        PostAs.getview.RemoveViewFromParent
        mapPage.RootPanel.AddView(PostAs.getview, PostAs.getview.Left, PostAs.getview.Top, PostAs.getview.Width, PostAs.getview.Height)
    End If
End Sub

Sub getDetails
    
End Sub

Sub btnBack_Click
    Global.doBack(0)
End Sub

Sub mmm_CameraChange (Position As CameraPosition)
    Log("test" & map.MyLocation)
'    Dim loc As LatLng
'    loc.Initialize()
'   
    
End Sub

Sub ivDropDown_Click
    PostAs.showpostaspnl
End Sub
 
Upvote 0
Top