I have been creating a few of my own customview and find it a little weird as such :
This is the 'header' of my custom view
B4X:
Public Sub Initialize (Callback As Object, EventName As String)
mEventName = EventName
mCallBack = Callback
End Sub
Public Sub DesignerCreateView (Base As Panel, Lbl As Label, Props As Map)
mBase = Base
CallSubDelayed2(Me, "AfterLoadLayout", Props)
End Sub
Private Sub AfterLoadLayout(Props As Map)
mBase.LoadLayout("Bar") '<<<---------------------LOADING FROM EXTERNAL .bal FORM
mBase.Color=xui.Color_Transparent
End Sub
In my application starts up :
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.LoadLayout("MainPage")
Sleep(500)'<<---- DELAY DUE TO LOAD FORM FROM CUSTOM VIEW ???????
'-----------------------------------------------------------------------------------------------------------
TW_Bar1.TW_Init_View(2%x,4%x,20dip,5dip,1000)
TW_Bar1.TW_CenterLabel1.Visible=True <<------ EXPOSED LABEL (Set as Public) IN CUSTOMVIEW
Note that when i call my customview, I HAVE to put a delay Sleep(500) before i can access to any exposed objects in my custom views. Else it will have error have error :
Object was not initialized (B4IPanelView)
The Sleep basically enables the 'mBase.LoadLayout("Bar")' to finish loaded before i can call any object INSIDE the customview
My question is :
1) Is this even the right way to of doing it?
2) How can i make do WITHOUT Sleep(500)
Thank you Klaus / LucaMs. Please find attached zip for my customview. Its basically a customview - which you can configure during onload to change its appearance.
I need to take out the Sleep(500)... as this sleep causes blank screen
Sorry, but I do not really understand what exactly you want to do, it is very confusing, at leas for me.
You are mixing up CustomView and adding views in the code.
You are defining views in the CustomView with a layout.
Then you define others in the main code, very strange !?
You need to explain more in detail what exactly you want to do.
In my mind, everything you want to do in the CustomView should be done in the CustomView module.
If I understand well, it seems that you try to add the CustomView in the code.
If this is the case you could add a routine in the CustomView module as explained in the B4X Custom views booklet chapter 4.3 Adding a custom view by code.
Yes, I know, Erel does not like it, but it is possible.
I don't see the problem of loading the custom layout, and there is no reason to add Sleep(500) when loading the layout.
you example:
Custom View
Add Ready event:
B4X:
#Event: Click(svalue as String)
#Event: Ready
Sub Class_Globals
Private mEventName As String 'ignore
Private mCallBack As Object 'ignore
Private mBase As B4XView
Private PnlShadow As Panel
Public TW_BackPanel As B4XView
Public TW_BackImgView As B4XView
Public TW_CenterLabel1 As B4XView
Public TW_CenterLabel2 As B4XView
Public TW_Button(10) As B4XView
Public TW_SmallLabel(10) As B4XView
Public TW_SmallImgView(10) As B4XView
Public TW_TxtInput As B4XView
Dim xui As XUI
Private gRadius As Int=0
End Sub
Public Sub Initialize (Callback As Object, EventName As String)
mEventName = EventName
mCallBack = Callback
End Sub
Public Sub DesignerCreateView (Base As Panel, Lbl As Label, Props As Map)
mBase = Base
CallSubDelayed2(Me, "AfterLoadLayout", Props)
End Sub
Private Sub AfterLoadLayout(Props As Map)
mBase.LoadLayout("Bar")
mBase.Color=xui.Color_Transparent
If SubExists(mCallBack, mEventName & "_Ready") Then
CallSub(mCallBack, mEventName & "_Ready")
End If
End Sub
main page Private Sub TW_Bar1_Ready
B4X:
#Region Shared Files
#CustomBuildAction: folders ready, %WINDIR%\System32\Robocopy.exe,"..\..\Shared Files" "..\Files"
'Ctrl + click to sync files: ide://run?file=%WINDIR%\System32\Robocopy.exe&args=..\..\Shared+Files&args=..\Files&FilesSync=True
#End Region
'Ctrl + click to export as zip: ide://run?File=%B4X%\Zipper.jar&Args=Project.zip
Sub Class_Globals
Private Root As B4XView
Private xui As XUI
Private TW_Bar1 As TW_Bar
End Sub
Public Sub Initialize
B4XPages.GetManager.TransitionAnimationDuration = 0
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.LoadLayout("MainPage")
End Sub
Private Sub TW_Bar1_Ready
TW_Bar1.TW_Init_View(0%x,4%x,20dip,5dip,1000)
TW_Bar1.TW_BackImgView_SetImage(LoadBitmap(File.DirAssets,"banner.jpg"))
TW_Bar1.TW_BackImgView.Visible=True
For x=0 To 4
TW_Bar1.TW_SetButton_TextColor(TW_Bar1.TW_Button(x),xui.Color_White)
TW_Bar1.TW_Button(x).Font=xui.CreateFontAwesome(30)
TW_Bar1.TW_Button(x).Color=xui.Color_Transparent
TW_Bar1.TW_Button(x).Visible=True
Next
TW_Bar1.TW_Button(0).Top=6%x
TW_Bar1.TW_Button(0).Text=Chr(0xF039)
TW_Bar1.TW_Button(1).Text=""
TW_Bar1.TW_Button(2).Text=""
TW_Bar1.TW_Button(3).Text=""
TW_Bar1.TW_Button(4).Top=6%x
TW_Bar1.TW_Button(4).Text=Chr(0xF013)
'-----------------------------------------------------------------
TW_Bar1.TW_CenterLabel1.left=20%x
TW_Bar1.TW_CenterLabel1.Top=4%x
TW_Bar1.TW_CenterLabel1.Height=14%x
TW_Bar1.TW_CenterLabel1.Font=xui.CreateDefaultBoldFont(20)
TW_Bar1.TW_CenterLabel1.Text="Malaysia zoologist"
TW_Bar1.TW_CenterLabel1.Color=xui.Color_Transparent
TW_Bar1.TW_CenterLabel1.TextColor=xui.Color_White
TW_Bar1.TW_CenterLabel1.Visible=True
'-----------------------------------------------------------------
TW_Bar1.TW_CenterLabel2.Text="Welcome - Selamat Datang - 欢迎"
TW_Bar1.TW_CenterLabel2.left=20%x
TW_Bar1.TW_CenterLabel2.Top=14%x
TW_Bar1.TW_CenterLabel2.TextSize=13
TW_Bar1.TW_CenterLabel2.Color=xui.Color_Transparent
TW_Bar1.TW_CenterLabel2.TextColor=xui.Color_Yellow
TW_Bar1.TW_CenterLabel2.Visible=True
End Sub
Search autocomplete places or addresses. Is a custom view that can be used inside or outside of the goolgemap. Note: It has search in different providers of location services among them: GoogleMap Nominatim LocationIQ MapQuest Bing Maps Mapbox Others B4A:
Klaus : Sorry for not explaining clearly what i wanted to achieve here. Basically i wanted to build a widget with some labels, Imageviews and buttons (10 each). When you place these widget to use, You can directly manipulate/change the properties of these labels from your code (text/height/top/... etc etc) as these labels , Imagesviews, buttons are assigned Public in the widget (Instead of me having to create that many properties under Props).
oparra : Thanks and its a brilliant idea of what you have done. Tested on android without problem.. but still i have problem using the same method for IOS.
In IOS, I have assigned it this way :
B4X:
Private Sub AfterLoadLayout(Props As Map)
mBase.LoadLayout("Bar")
mBase.Color=xui.Color_Transparent
#if B4A
If SubExists(mCallBack, mEventName & "_Ready") Then
CallSub(mCallBack, mEventName & "_Ready")
End If
#Else if B4i
If SubExists(mCallBack, mEventName & "_Ready",0) Then
Sleep(200) <<------- (Without this delay, IOS wont work
CallSub(mCallBack, mEventName & "_Ready")
End If
#End if
End Sub
I mean..in IOS it work.. but still need to place Sleep(200)
Public Sub DesignerCreateView (Base As Panel, Lbl As Label, Props As Map)
mBase = Base
Sleep(0)
CallSubDelayed2(Me, "AfterLoadLayout", Props)
End Sub
Private Sub AfterLoadLayout(Props As Map)
mBase.LoadLayout("Bar")
mBase.Color=xui.Color_Transparent
If SubExists(mCallBack, mEventName & "_Ready") Then
CallSub(mCallBack, mEventName & "_Ready")
End If
End Sub
Klaus : Sorry for not explaining clearly what i wanted to achieve here. Basically i wanted to build a widget with some labels, Imageviews and buttons (10 each). When you place these widget to use, You can directly manipulate/change the properties of these labels from your code (text/height/top/... etc etc) as these labels , Imagesviews, buttons are assigned Public in the widget (Instead of me having to create that many properties under Props).
oparra : Thanks and its a brilliant idea of what you have done. Tested on android without problem.. but still i have problem using the same method for IOS.
In IOS, I have assigned it this way :
B4X:
Private Sub AfterLoadLayout(Props As Map)
mBase.LoadLayout("Bar")
mBase.Color=xui.Color_Transparent
#if B4A
If SubExists(mCallBack, mEventName & "_Ready") Then
CallSub(mCallBack, mEventName & "_Ready")
End If
#Else if B4i
If SubExists(mCallBack, mEventName & "_Ready",0) Then
Sleep(200) <<------- (Without this delay, IOS wont work
CallSub(mCallBack, mEventName & "_Ready")
End If
#End if
End Sub
I mean..in IOS it work.. but still need to place Sleep(200)
Private Sub AfterLoadLayout(Props As Map)
mBase.LoadLayout("Bar")
mBase.Color=xui.Color_Transparent
#if B4i
Sleep(200)
#End if
If SubExists(mCallBack, mEventName & "_Ready") Then
CallSub(mCallBack, mEventName & "_Ready")
End If
End Sub
Klaus, Thank you for your effort. I think i need to change strategy... I guess still the most reliable way for this to work for both Android and IOS is to create properties in the CustomView.
I have lots to add ... Thank you again for finding out.
*Oh by the way.. above Sleep(0).. still does not work. Unless i put some sleep(200). Don't really know if it is because of my iPhone6 which is too old.
* Note for ios, SubExists(mCallBack, mEventName & "_Ready",0) <<----- there are additional parameter 0
Sub Class_Globals
Private mEventName As String 'ignore
Private mCallBack As Object 'ignore
Private mBase As B4XView Private PnlShadow As Panel
Public TW_BackPanel As B4XView
Public TW_BackImgView As B4XView
Public TW_CenterLabel1 As B4XView
Public TW_CenterLabel2 As B4XView
Public TW_Button(10) As B4XView
Public TW_SmallLabel(10) As B4XView