Android Question [SOLVED] - B4XPages - Loading layouts

rleiman

Well-Known Member
Licensed User
Longtime User
Greetings,

I just migrated a working non-B4XPages app over to B4XPages because CallSubDelayed was not working correctly when the old app did not have focus. I was advised to migrate to B4XPages. That issue has been resolved just by doing the migration. It seems that loading layouts is done differently in B4XPages. The screen shots will show what the original app screens looked like vs the same screens in B4XPages.

This layout that's loaded is the same in both apps:

Screenshot 2020-11-26 at 20.14.20.png

The original app screen shots:
Screenshot_20201126-201040.jpgScreenshot_20201126-201048.jpg

The same shots in B4XPages:
Screenshot_20201126-201040.jpgScreenshot_20201126-200056.jpg

On the screen shot of the xCLV in B4XPages, the list is shown but the background is washed out in a whitish colour.

Here's the coding from the original app that slides the panel off the screen before calling the sub routine that builds the xCLV:
B4X:
Sub ImageViewSongList_Click

    Activity.LoadLayout("SongList") ' This layout also contains a custom list view.

    cLvSelSongList.Initialize(clvSongList)
    cLvSelSongList.Mode = cLvSelSongList.MODE_SINGLE_ITEM_PERMANENT

    ' Make panel slide down out of site.
    '-----------------------------------
    PanelMenu.SetLayoutAnimated(300, 0, Activity.Height, Activity.Width, _
        Activity.Height)
   
    BuildTheSongListCustomListView

    If blnAsongIsPlaying And ServiceModule.blnScheduleIsPlayingSong = False Then ' Turn the song off.
        ImageViewPlayCurrentSong_Click
    End If
End Sub

This is the B4XPages version of the same coding:
B4X:
Sub ImageViewSongList_Click

    Root.LoadLayout("SongList") ' This layout also contains a custom list view.

    cLvSelSongList.Initialize(clvSongList)
    cLvSelSongList.Mode = cLvSelSongList.MODE_SINGLE_ITEM_PERMANENT

    ' Make panel slide down out of site.
    '-----------------------------------
    PanelMenu.SetLayoutAnimated(300, 0, Root.Height, Root.Width, _
        Root.Height)
   
    BuildTheSongListCustomListView

    If blnAsongIsPlaying And ServiceModule.blnScheduleIsPlayingSong = False Then ' Turn the song off.
        ImageViewPlayCurrentSong_Click
    End If
End Sub

I thought all I needed to do was replace "Activity" with "Root" but I guessed wrong.

Here's the codING I use for building the xCLV. It's the same in both the old app and in B4XPages :
B4X:
Sub BuildTheSongListCustomListView
   
    clvSongList.Clear

    ButtonSongDetails.Visible = False
   
    ' Add 10 items to the list view.
    '-------------------------------
    For intIndex = 0 To 2
       
        ' typValues holds values from a custom type object that can be accessed from the values
        ' parameter of the ItemClick handler of this xCLV.
        '--------------------------------------------------------------------------------------
        Dim typValues As typSongsListItemValues

        ' Adding items to the list view requires a Panel created in code.
        '----------------------------------------------------------------
        Dim p As B4XView = xui.CreatePanel("")

        ' This is the size for the panel and it will be animated.
        '--------------------------------------------------------
        p.SetLayoutAnimated(0, 0, 0, PanelSongList.Width, 200dip)
       
        p.LoadLayout("SongListCard")

        ' Populate the views with values from the database.
        ' Doing the replace here will make sure unchecked days will not be displayed in the list.
        '----------------------------------------------------------------------------------------
        LabelSongTitle.Text = kvs.Get("Song" & (intIndex + 1) & "Title")

        LabelSchedule.Text = LTrim(kvs.Get("Song" & (intIndex + 1) & "Schedule"))
        LabelSchedule.Text = LabelSchedule.Text.Replace("100 ", "")
        LabelSchedule.Text = LabelSchedule.Text.Replace("200 ", "")
        LabelSchedule.Text = LabelSchedule.Text.Replace("300 ", "")
        LabelSchedule.Text = LabelSchedule.Text.Replace("400 ", "")
        LabelSchedule.Text = LabelSchedule.Text.Replace("500 ", "")
        LabelSchedule.Text = LabelSchedule.Text.Replace("600 ", "")
        LabelSchedule.Text = LabelSchedule.Text.Replace("700 ", "")
        LabelSchedule.Text = LTrim(LabelSchedule.Text)

        LabelScheduleFromUntil.Text = _
            kvs.Get("Song" & (intIndex + 1) & "ScheduleActiveFrom") & " To " & _
            kvs.Get("Song" & (intIndex + 1) & "ScheduleActiveUntil")

        If kvs.Get("Song" & (intIndex + 1) & "ScheduleIsActivated") Then
            ImageViewSongScheduleIsActivated.Bitmap = _
                        LoadBitmap(File.DirAssets, "light-on-icon.png")
        Else
            ImageViewSongScheduleIsActivated.Bitmap = _
                        LoadBitmap(File.DirAssets, "light-off-icon.png")
        End If
       
        Select intIndex + 1
           
            Case 1
                If blnAsongIsPlaying And ServiceModule.blnSchedule1IsPlayingSong Then

                    ImageViewPlayPauseSong.Bitmap = _
                        LoadBitmap(File.DirAssets, "pause-circle.png")
                Else

                    ImageViewPlayPauseSong.Bitmap = _
                        LoadBitmap(File.DirAssets, "play-circle.png")
                End If

            Case 2
                If blnAsongIsPlaying And ServiceModule.blnSchedule2IsPlayingSong Then

                    ImageViewPlayPauseSong.Bitmap = _
                        LoadBitmap(File.DirAssets, "pause-circle.png")
                Else

                    ImageViewPlayPauseSong.Bitmap = _
                        LoadBitmap(File.DirAssets, "play-circle.png")
                End If

            Case 3
                If blnAsongIsPlaying And ServiceModule.blnSchedule3IsPlayingSong Then

                    ImageViewPlayPauseSong.Bitmap = _
                        LoadBitmap(File.DirAssets, "pause-circle.png")
                Else

                    ImageViewPlayPauseSong.Bitmap = _
                        LoadBitmap(File.DirAssets, "play-circle.png")
                End If
        End Select

        ' This is where the item row is added to the list view.
        ' Each list item has a set of Type structure elements associated with it.
        '------------------------------------------------------------------------
        clvSongList.Add(p,typValues)
    Next

    If blnComingBackFromSongDetails Then

        blnComingBackFromSongDetails = False
       
        ButtonSongDetails.Visible = True
   
        clvSongList.ScrollToItem(intCurrentSongSelected - 1)
        cLvSelSongList.ItemClicked(intCurrentSongSelected - 1)
    End If
End Sub

What did I miss when doing the migration?

Thanks.
 

LucaMs

Expert
Licensed User
Longtime User
I thought all I needed to do was replace "Activity" with "Root" but I guessed wrong.
No, you're right; Root takes the place of the Activity as base container of your Views (you can "forget" the existence of the Activity Main).

You have an image as background of the Activity (more exactly of your layout), an image that you could add to your layout as Erel suggested, that is, add an ImageView under the other Views.

Another way, more similar to the Activity background, is to load the image into the Root but at runtime (so you don't have to change the layouts):
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("SongList")
    Root.SetBitmap(xui.LoadBitmapResize(File.DirAssets, "robin background.png", Root.Width, Root.Height, True))
End Sub

[Note: xui.LoadBitmapResize is the same of LoadBitmapResize but it is cross-platform]
 
Last edited:
Upvote 0

rleiman

Well-Known Member
Licensed User
Longtime User
Thanks everyone for the replies. Yes, the image is the difference. Later today I will try adding the image as described by LucaMs. All of you are the best. šŸ‘
 
Upvote 0

rleiman

Well-Known Member
Licensed User
Longtime User
Works like a dream. šŸ˜Š

I will use xui.LoadBitmapResize for the rest of all the other layouts in the app.

Here's the sub routine that loads the layout including the xui.LoadBitmapResize.

B4X:
Sub ImageViewSongList_Click

    Root.LoadLayout("SongList") ' This layout also contains a custom list view.
        
    Root.SetBitmap(xui.LoadBitmapResize(File.DirAssets, "robin background.png", _
        Root.Width, Root.Height, False))

    cLvSelSongList.Initialize(clvSongList)
    cLvSelSongList.Mode = cLvSelSongList.MODE_SINGLE_ITEM_PERMANENT

    ' Make panel slide down out of site.
    '-----------------------------------
    PanelMenu.SetLayoutAnimated(300, 0, Root.Height, Root.Width, _
        Root.Height)
    
    BuildTheSongListCustomListView

    If blnAsongIsPlaying And ServiceModule.blnScheduleIsPlayingSong = False Then ' Turn the song off.
        ImageViewPlayCurrentSong_Click
    End If
End Sub

Out of curiosity, do you know why B4XPages didn't pick up the BitmapDrawable from the designer when the original app did pick it up?
 
Upvote 0

rleiman

Well-Known Member
Licensed User
Longtime User
If I understand your question correctly, the answer I think is that in the Designer you set the Activity background, not the layout background.
View attachment 103704

Erel will be more precise than me.
Thanks. Maybe in a future B4X update Erel will include Root Properties if the user is doing a B4XPages app when the user opens the designer.
 
Upvote 0
Top