1. *** New version of B4J is available ***
    B4J v7.8
    Dismiss Notice

Android Question [Closed] Reusing layout, how to reuse/factor related code?

Discussion in 'Android Questions' started by Alexis Martial, Apr 13, 2019.

  1. Alexis Martial

    Alexis Martial Member Licensed User

    Layout and their scripts are fantastic!

    In my current application, I have such a layout that is actually for an overlay/dialog and I'm reusing it in 2 activities.

    However, I can't find a way to reuse the code that handle them (filling the fields, handling the events, etc).

    I could write a dedicated module but can't use Designer to declare the different views into this module.
    I could pass the enclosing panel to each of this module routine, but that means I would have to manually find each child view [which I guess is what B4A is doing behind the scene].
    Issue is this make it very difficult to maintain.

    Any suggestion for those that have done similar things?
     
  2. klaus

    klaus Expert Licensed User

    Make a CustomView.
     
  3. Alexis Martial

    Alexis Martial Member Licensed User

    Thaks for the starting tip, let me find some example ;-)
     
  4. klaus

    klaus Expert Licensed User

  5. Alexis Martial

    Alexis Martial Member Licensed User

    Thanks,

    I went through it and various examples and they are running fine when I compiled them.

    I still didn't manage to make mine works.
    I stripped down my code to the minimum.
    Basically my custom view is now just loading a layout.
    I tried with CustomView and CustomView XUI without success :-(

    Stripped down code of my custom view:

    Code:
    Sub Class_Globals
        
    Private mEventName As String 'ignore
        Private mCallBack As Object 'ignore
        Private mBase As Panel
        
    Private Button1 As Button
    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
        mBase.LoadLayout(
    "Basic")
    End Sub
    the Layout "Basic" only include one button since I wanted to test with the simplest case.

    My Custom view Initialize and DesignerCreateView methods are called [I put breakpoints there]
    But the call to LoadLayout fails with:

    Error occurred on line: 56 (QRCodeSummaryView)
    java.lang.RuntimeException: java.lang.ClassCastException: sg.com.idigo.pokeelite.b4xtable cannot be cast to android.widget.TextView
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:170)
    at anywheresoftware.b4a.objects.PanelWrapper.LoadLayout(PanelWrapper.java:134)
    ...

    And I can't understand where the "sg.com.idigo.pokeelite.b4xtable cannot be cast to android.widget.TextView" come from !
    Note that I have a B4XTable in the main activity layout that include my custom view, but I can't see how they relate.

    Any clues will be much then welcome !
     
  6. Alexis Martial

    Alexis Martial Member Licensed User

    Another interesting thing is part of the error list below the ones I already included:
    ...
    Caused by: java.lang.ClassCastException: sg.com.idigo.pokeelite.b4xtable cannot be cast to android.widget.TextView
    at anywheresoftware.b4a.objects.CustomViewWrapper.AfterDesignerScript(CustomViewWrapper.java:44)
    at anywheresoftware.b4a.keywords.LayoutBuilder.loadLayout(LayoutBuilder.java:162)
    ... 34 more
     
  7. Alexis Martial

    Alexis Martial Member Licensed User

    I did another test, using this customview in another activity, I got similar error, but this time not related to B4XTable:
    java.lang.RuntimeException: java.lang.ClassCastException: java.lang.String cannot be cast to android.widget.TextView

    So I guess I'm missing something very basic
     
  8. klaus

    klaus Expert Licensed User

    You should post your test project so we can see what exactly you have done and find the probelm.
     
  9. Alexis Martial

    Alexis Martial Member Licensed User

    Great, let me build a simplified test project that hopefully will replicate the issue ;-)
     
  10. Alexis Martial

    Alexis Martial Member Licensed User

    Find attached.
    Simplified to the max.

    Main Activity load "Main" layout which include a panel that manually load "SubLayout" layout without issue, than the LoadLayoutCustomView that is supposed to load the same layout but fail with similar exception/error I faced in my full project.

    Thanks so much for your help !
     

    Attached Files:

  11. klaus

    klaus Expert Licensed User

    Change your code to:
    Code:
    'Base type must be Object
    Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
        mBase = Base
     
        CallSubDelayed(Me, 
    "LoadLayout")
     
    End Sub

    Private Sub Base_Resize (Width As Double, Height As Double)
     
    End Sub

    Private Sub LoadLayout
        mBase.LoadLayout(
    "SubLayout")
    End Sub
    It's the first time that I loaded a Layout in a CustomView.
    I found the solution searching the forum in this thread: CustomView-Library with LoadLayout ?
    In the project below, I changed a bit the SubLayout to see what happens.
     

    Attached Files:

    Last edited: Apr 14, 2019
    Erel likes this.
  12. Alexis Martial

    Alexis Martial Member Licensed User

    If I call B4X a gem, both you and Erel are the Gem Carving Artists ;-)
     
  13. Alexis Martial

    Alexis Martial Member Licensed User

    So it's a timing/initialization order related stuff.
    Let me apply this ASAP to my real project ;-)

    Thanks again.

    PS: is there a way to contribute to both Erel and you work on B4X ?
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    It is a bit simpler to use Sleep:
    Code:
    Public Sub DesignerCreateView (Base As Object, Lbl As Label, Props As Map)
        mBase = Base
       Sleep(
    0)
        mBase.LoadLayout(
    "SubLayout")
     
    End Sub
     
    klaus likes this.
  15. klaus

    klaus Expert Licensed User

    Interesting!
    I will add it in theCustomViews Booklet.
     
  16. MarkusR

    MarkusR Well-Known Member Licensed User

    there was also a way to load a layout in a class and get the events there.

    your class "MyClass"
    Code:
    Sub Class_Globals
        
    Private xui As XUI
        
        
    'Private ButtonSave As B4XView
    End Sub

    Public Sub Initialize(Parent As B4XView)
         
        Parent.LoadLayout(
    "YourLayout")
            
    End Sub

    'Sub ButtonSave_Click
       
     
    '  Log("ButtonSave_Click")

    'End Sub
    used in a activity
    Code:
    Sub Globals
        
    'These global variables will be redeclared each time the activity is created.
        'These variables can only be accessed from this module.
        Dim MyClass1 As MyClass

    End Sub

    Sub Activity_Create(FirstTime As Boolean)

       MyClass1.Initialize(
    Activity)

    End Sub
     
  17. Alexis Martial

    Alexis Martial Member Licensed User

    Wahoo !
    3 solutions to my problem, now confused, which one to choose ?
    :p
     
  18. klaus

    klaus Expert Licensed User

    I suggest you Erels solution with Sleep(0).
     
  19. Alexis Martial

    Alexis Martial Member Licensed User

    I also went for this one for now.

    However MarkusR option is a very good one when in need to decorrelate the Initialization and the Loading ;-)
     
    MarkusR likes this.
  20. klaus

    klaus Expert Licensed User

    The option of MarkusR is not for a CustomView.
    The signature of the Initialize routine for a CustomView is:
    Public Sub Initialize (Callback As Object, EventName As String)
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice