German Problem mit DoEvents und keine Lösung mit Sleep(0)

ziwalig

Member
Licensed User
Longtime User
Hallo Zusammen

Ich habe vor ca. 10 Jahre meine Zeit- und Auftragsbearbeitung-App geschrieben. Durch die vielen Android Änderungen und Updates ist meine App immer instabiler geworden. Ich habe versucht, die MsgBox und die DoEvents zu ersetzen, weil ich darin die Ursache der Abstürze vermutete. Leider kann ich nicht alle ersetzen, weil ich viele MsgBox-Anweisungen in statischen Modulen verwende und dort nicht funktioniert. Das zweite Problem ist momentan aber vor allem ein DoEvent in einer Prozedur eines statischen Moduls.

Mit diesem Code und der Höhe -2 füge ich dynamisch hohe Buttons in die Aktivität ein und erhalte immer die effektive Höhe der Buttons zurück. Ich benötige die effektive Höhe, damit ich weitere Elemente unter dem Button platzieren kann.

Wenn ich DoEvents durch Sleep(0) ersetze, werden alle Elemente übereinander eingefügt.

Hat jemand eine Idee wie ich meinen Code anpassen muss damit der Button eingefügt wird und ich die effektive Höhe zurück erhalte.

B4X:
Sub AddImgButton (objActivity As Activity, objView As Panel, objButton As Button, objBitmap As Bitmap, intBmpHeihgt As Int, intLeft As Int, intTop As Int, intWidth As Int, intHeihgt As Int)

    Dim imgImage As ImageView
    Dim objReflector As Reflector

    If objBitmap.IsInitialized Then
        imgImage.Initialize("")
        imgImage.Bitmap = objBitmap
    End If

    If intHeihgt = -2 Then
        objActivity.AddView(objButton, objActivity.Width, objActivity.Top, intWidth, intHeihgt)
        objButton.Padding = Array As Int (10dip, 10dip, intBmpHeihgt + 10dip, 10dip)
        DoEvents
        objReflector.Target = objButton
        intHeihgt = objReflector.RunMethod("getHeight")
        objButton.RemoveView
    End If
    
    objView.AddView(objButton, intLeft , intTop, intWidth, intHeihgt)
    objButton.Height = intHeihgt

    If Bit.And(objButton.Gravity, 0xf0) = Gravity.CENTER_VERTICAL Then
        intTop = intTop + (intHeihgt/2) - (intBmpHeihgt/2) - 1dip
    Else If Bit.And(objButton.Gravity, 0xf0) = Gravity.TOP Then
        intTop = intTop -1dip
    End If
    
    If objBitmap.IsInitialized Then objView.AddView(imgImage, intLeft + intWidth - intBmpHeihgt - 10dip , intTop , intBmpHeihgt, intBmpHeihgt)

End Sub
 

zed

Active Member
Licensed User
Welche Elemente? Rufen Sie die SUB-Schleife auf? Warum DoEvent?
Vielleicht verwenden Sie WaitFor.
Wir haben nicht genügend Informationen, um eine korrekte Antwort zu geben.
 
Upvote 0

ziwalig

Member
Licensed User
Longtime User
Welche Elemente? Rufen Sie die SUB-Schleife auf? Warum DoEvent?
Vielleicht verwenden Sie WaitFor.
Wir haben nicht genügend Informationen, um eine korrekte Antwort zu geben.
Ich habe für alle Elementtypen (Button, Edittext usw.) solche SUB-Schleife, damit ich die Elemente nach meinen Vorstellungen Formatieren/Darstellen kann.

Diese SUB AddImgButton erstellt in der Activity einen formatiertes Button-Element mit einem überlagerten Image und gibt in intHeihgt die effektive Höhe des Elementes zurück. Ich brauche die effektive Höch, damit ich mit einem Abstand von 5px unter dem Element ein neues einfügen kann. Wenn ich kein DoEvens verwende, werden alle Elemente übereinandergelegt, weil hight -2 zurück gibt. Das eingefügte Element wird wieder gelöscht um mit der effektiven Höhe das eigentliche Element in die Acivity einzufügen. WaitFor kann ich, nach meiner Information, in einem statischen Modul nicht verwenden.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
WaitFor kann ich, nach meiner Information, in einem statischen Modul nicht verwenden
dann benutze eine Klasse. sleep und wait for sind hier kein Problem.
 
Upvote 0

ziwalig

Member
Licensed User
Longtime User
dann benutze eine Klasse. sleep und wait for sind hier kein Problem.
Danke DonManfred für deinen Input.

Ja wahrscheinlich, nein, du hast sicher recht. Ich programmiere zwar schon sein über 30 Jahren, aber ich habe noch nie eine Klasse selbst geschrieben. Ich komme aus der Access-VBA-Welt und dort geht das meiste auch ohne eigene Klassen. Ich muss mal schauen, wie ich eine solche selbst aufbauen muss, damit diese keine Leichen von unbenützten Objekten hinterlässt.

Kennst du vielleicht einen Link, der mir schnell den Aufbau eigener sauberen Klassen erläutert. Ich gehe davon aus, dass ich für meine Bedürfnisse eine «Standard Class» brauche und nicht «Custom View».
 
Upvote 0

b4x-de

Active Member
Licensed User
Longtime User
Alternativ könntest du die Buttons auch aufgeben und eine schöne und moderne CustomListView verwenden, deren Items auf die Click-Events reagieren.
 
Upvote 0

ziwalig

Member
Licensed User
Longtime User
Alternativ könntest du die Buttons auch aufgeben und eine schöne und moderne CustomListView verwenden, deren Items auf die Click-Events reagieren.
Danke für deinen Beitrag. Aber obwohl ich das Forum durchsucht hab finde ich kein Beispiel mit dynamischer Höhe. Ich habe z.Bsp. einer Activity welche einen TabHost mit zwei Tabs enthält. In beiden Tabs sind ScrollViews enthalten und in diese füge ich dann Buttons und Labels ein. Die Buttons und Labels müssen dynamische Höhe haben, je nach Text. Wie könnte ich das mit CustomListView lösen?
 
Upvote 0

b4x-de

Active Member
Licensed User
Longtime User
Hier ein Auszug aus dem angehängten Beispiel, wie man die Höhe der Panels innerhalb einer CustomListView dynamisch anpassen kann. Es basiert auf der Idee, mit den StringUtils die Höhe des Labels zu messen und dann alle Elemente innerhalb des Panels und anzupassen.

B4X:
Private Sub show()
    Dim su As StringUtils
  
    Dim intHeightOld As Int
    Dim intHeightNew As Int
    Dim intHeightDiff As Int
  
    Dim strButtonLabel As String
  
    clvFlexiButtonList.Clear
  
    For i = 0 To 20
        Dim pnlTemp As B4XView
        pnlTemp = xui.CreatePanel("")
        pnlTemp.SetLayoutAnimated(0,0,0, clvFlexiButtonList.AsView.Width, 100dip)
        pnlTemp.LoadLayout("pnlFlexiButton")
      
        ' Create text of random size as button label
        strButtonLabel = strLoremIpsum.SubString2(0, Rnd(20, 500))
      
        ' Measure the height of the label
        intHeightOld = su.MeasureMultilineTextHeight(lblFlexiButtonLabel, "")
        intHeightNew = su.MeasureMultilineTextHeight(lblFlexiButtonLabel, strButtonLabel)
        intHeightDiff = intHeightNew - intHeightOld

        ' Resize the gui controls to the new height required     
        pnlTemp.Height = pnlTemp.Height + intHeightDiff
        pnlFexiButton.Height = pnlFexiButton.Height + intHeightDiff
        lblFlexiButtonLabel.Height = lblFlexiButtonLabel.Height + intHeightDiff
        imgFlexiButtonIcon.Top = pnlFexiButton.Height / 2 - imgFlexiButtonIcon.Height / 2
      
        ' Apply text and icon to the resized gui controls
        lblFlexiButtonLabel.Text = strButtonLabel
        imgFlexiButtonIcon.Bitmap = convertFontAwesomeToBitmap(chrIcon(i Mod 5), 50)
      
        ' load everything into the panel, use a unique identification for each button
        clvFlexiButtonList.Add(pnlTemp, "btnExample" & i)

    Next
End Sub

Hinweise:
  • strLoremIpsum ist ein sehr langer String mit Beispieltext, der als Konstante deklariert wurde.
  • chrIcon() ist ein Array, das exemplarische FontAwesome-Icons speichert
  • convertFontAwesomeToBitmap() erzeugt die Bitmaps
  • Erfordert die Bibliotheken XUI, XUI Views und StringUtils.
 

Attachments

  • FlexiButtonClvExample.zip
    12 KB · Views: 135
Last edited:
Upvote 0

ziwalig

Member
Licensed User
Longtime User
Hier ein Auszug aus dem angehängten Beispiel, wie man die Höhe der Panels innerhalb einer CustomListView dynamisch anpassen kann. Es basiert auf der Idee, mit den StringUtils die Höhe des Labels zu messen und dann alle Elemente innerhalb des Panels und anzupassen.

B4X:
Private Sub show()
    Dim su As StringUtils
 
    Dim intHeightOld As Int
    Dim intHeightNew As Int
    Dim intHeightDiff As Int
 
    Dim strButtonLabel As String
 
    clvFlexiButtonList.Clear
 
    For i = 0 To 20
        Dim pnlTemp As B4XView
        pnlTemp = xui.CreatePanel("")
        pnlTemp.SetLayoutAnimated(0,0,0, clvFlexiButtonList.AsView.Width, 100dip)
        pnlTemp.LoadLayout("pnlFlexiButton")
     
        ' Create text of random size as button label
        strButtonLabel = strLoremIpsum.SubString2(0, Rnd(20, 500))
     
        ' Measure the height of the label
        intHeightOld = su.MeasureMultilineTextHeight(lblFlexiButtonLabel, "")
        intHeightNew = su.MeasureMultilineTextHeight(lblFlexiButtonLabel, strButtonLabel)
        intHeightDiff = intHeightNew - intHeightOld

        ' Resize the gui controls to the new height required    
        pnlTemp.Height = pnlTemp.Height + intHeightDiff
        pnlFexiButton.Height = pnlFexiButton.Height + intHeightDiff
        lblFlexiButtonLabel.Height = lblFlexiButtonLabel.Height + intHeightDiff
        imgFlexiButtonIcon.Top = pnlFexiButton.Height / 2 - imgFlexiButtonIcon.Height / 2
     
        ' Apply text and icon to the resized gui controls
        lblFlexiButtonLabel.Text = strButtonLabel
        imgFlexiButtonIcon.Bitmap = convertFontAwesomeToBitmap(chrIcon(i Mod 5), 50)
     
        ' load everything into the panel, use a unique identification for each button
        clvFlexiButtonList.Add(pnlTemp, "btnExample" & i)

    Next
End Sub

Hinweise:
  • strLoremIpsum ist ein sehr langer String mit Beispieltext, der als Konstante deklariert wurde.
  • chrIcon() ist ein Array, das exemplarische FontAwesome-Icons speichert
  • convertFontAwesomeToBitmap() erzeugt die Bitmaps
  • Erfordert die Bibliotheken XUI, XUI Views und StringUtils.
Danke vielmals für deinen Vorschlag/Code und entschuldige bitte, dass ich erst jetzt reagiere, aber im Moment habe ich gerad viel um die Ohren. Sobald ich wieder etwas Zeit habe, werde ich deinen Code ausprobieren. Nochmals Danke.
 
Upvote 0
Top