AdrianZarr
New Member
in the note editor
when keyboard opens, some bottom text gets hidden behind the keyboard and i cant scroll it to view in order to see and edit it at all
i tried to use something like
Private Sub kb_HeightChanged (NewHeight As Int, OldHeight As Int)
but it never work
this is my current code
when keyboard opens, some bottom text gets hidden behind the keyboard and i cant scroll it to view in order to see and edit it at all
i tried to use something like
Private Sub kb_HeightChanged (NewHeight As Int, OldHeight As Int)
but it never work
this is my current code
B4X:
Sub Class_Globals
Private Root As B4XView
Private xui As XUI
Private sv As ScrollView
Private svEditor As ScrollView
Private pnlEditorInner As B4XView
Private pnlContent As B4XView
Private nav As NavigationBar
Private kb As IME
' Data Storage
Private NotesList As List
Private Const FILE_NAME As String = "user_notes.json"
' Editor UI
Private pnlEditor As B4XView
Private etTitle As EditText
Private etBody As EditText
Private CurrentIndex As Int = -1 ' -1 for new note
' Constants
Private Const COLOR_PRIMARY As Int = 0xFF2196F3
Private Const COLOR_BG As Int = 0xFFF0F2F5
End Sub
Public Sub Initialize As Object
Return Me
End Sub
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.Color = COLOR_BG
B4XPages.SetTitle(Me, "Clinical Notes")
' Initialize Navigation
nav.Initialize(Root, "Notes")
kb.Initialize("kb")
kb.AddHeightChangedEvent
' Initialize main ScrollView for rows
sv.Initialize(1000)
Root.AddView(sv, 0, 0, Root.Width, Root.Height - nav.NAV_HEIGHT)
pnlContent = sv.Panel
' Setup components
CreateEditorUI
CreateFAB
' Load existing data
LoadNotes
RefreshNoteRows
End Sub
Private Sub B4XPage_Disappear
' Reset the page state only when NAVIGATING away, not when the screen turns off.
' Sleep(0) allows the B4XPages manager to update the internal stack first.
Sleep(0)
Dim TopPage As B4XPageInfo = B4XPages.GetManager.GetTopPage
If TopPage = Null Or TopPage.B4XPage <> Me Then
sv.ScrollPosition = 0
End If
End Sub
' Intercept hardware back button to close editor instead of the app
Private Sub B4XPage_CloseRequest As ResumableSub
If pnlEditor.IsInitialized And pnlEditor.Visible Then
btnSave_Click ' Auto-save on back
Return False
End If
Return True
End Sub
Private Sub CreateFAB
Dim pnlFAB As B4XView = xui.CreatePanel("btnFAB")
' Position FAB above the bottom navigation bar
Root.AddView(pnlFAB, Root.Width - 76dip, Root.Height - nav.NAV_HEIGHT - 76dip, 56dip, 56dip)
pnlFAB.SetColorAndBorder(COLOR_PRIMARY, 0, 0, 28dip)
UIEffects.SetCircleRipple(pnlFAB)
Dim lbl As Label : lbl.Initialize("")
Dim xlbl As B4XView = lbl
xlbl.Text = Chr(0xE145) ' Material Add Icon
xlbl.Font = xui.CreateMaterialIcons(28)
xlbl.TextColor = xui.Color_White
xlbl.SetTextAlignment("CENTER", "CENTER")
pnlFAB.AddView(xlbl, 0, 0, 56dip, 56dip)
End Sub
Private Sub CreateEditorUI
' Full screen editor panel
pnlEditor = xui.CreatePanel("pnlEditor")
pnlEditor.Color = xui.Color_White
pnlEditor.Visible = False
Root.AddView(pnlEditor, 0, 0, Root.Width, Root.Height)
' Top Toolbar for Editor
Dim pnlToolbar As B4XView = xui.CreatePanel("")
pnlToolbar.Color = xui.Color_White
pnlEditor.AddView(pnlToolbar, 0, 0, Root.Width, 60dip)
' Back button (Save & Exit)
Dim lblBack As Label : lblBack.Initialize("btnSave")
Dim xBack As B4XView = lblBack
xBack.Text = Chr(0xE5C4) : xBack.Font = xui.CreateMaterialIcons(24)
xBack.TextColor = COLOR_PRIMARY : xBack.SetTextAlignment("CENTER", "CENTER")
pnlToolbar.AddView(xBack, 5dip, 5dip, 50dip, 50dip)
UIEffects.SetCircleRipple(xBack)
' Delete button
Dim lblDel As Label : lblDel.Initialize("btnDelete")
Dim xDel As B4XView = lblDel
xDel.Text = Chr(0xE872) : xDel.Font = xui.CreateMaterialIcons(24)
xDel.TextColor = 0xFFFF5252 : xDel.SetTextAlignment("CENTER", "CENTER")
pnlToolbar.AddView(xDel, Root.Width - 55dip, 5dip, 50dip, 50dip)
UIEffects.SetCircleRipple(xDel)
' Add a thin divider at the bottom of the toolbar to tightly separate it from content
Dim pnlDiv As B4XView = xui.CreatePanel("")
pnlDiv.Color = 0xFFEEEEEE
pnlToolbar.AddView(pnlDiv, 0, 59dip, Root.Width, 1dip)
' Input Fields
' Scrollable container for both title and body content
svEditor.Initialize(1000)
pnlEditor.AddView(svEditor, 0, 60dip, Root.Width, Root.Height - 60dip)
pnlEditorInner = svEditor.Panel
etTitle.Initialize("etTitle")
etTitle.Hint = "Title"
etTitle.Typeface = Typeface.DEFAULT_BOLD ' Keep bold for emphasis
etTitle.TextSize = 24 ' Increased text size for a more prominent title
etTitle.Color = xui.Color_Transparent
etTitle.SingleLine = False
etTitle.Gravity = Gravity.TOP
etTitle.Padding = Array As Int(5dip, 5dip, 5dip, 0)
' Position at 0dip to eliminate the gap between toolbar and content
pnlEditorInner.AddView(etTitle, 20dip, 0dip, Root.Width - 40dip, 50dip)
etBody.Initialize("etBody")
etBody.Hint = "Start typing..."
etBody.TextSize = 18
etBody.Color = xui.Color_Transparent
etBody.SingleLine = False
etBody.Gravity = Gravity.TOP
' Anchor Body at 0dip to keep the scroll position fixed
pnlEditorInner.AddView(etBody, 20dip, 0dip, Root.Width - 40dip, 200dip)
' Keep Title in front of Body so both are clickable and the title stays visible
etTitle.BringToFront
End Sub
Private Sub RefreshNoteRows
pnlContent.RemoveAllViews
Dim TopPos As Int = 15dip
If NotesList.Size = 0 Then
Dim lbl As Label : lbl.Initialize("")
Dim xlbl As B4XView = lbl
xlbl.Text = "No notes yet. Tap + to create one."
xlbl.TextColor = 0xFF9E9E9E
xlbl.SetTextAlignment("CENTER", "CENTER")
pnlContent.AddView(xlbl, 20dip, 100dip, Root.Width - 40dip, 40dip)
Return
End If
For i = 0 To NotesList.Size - 1
Dim m As Map = NotesList.Get(i)
Dim card As B4XView = xui.CreatePanel("NoteCard")
card.Tag = i
card.Color = xui.Color_White
' Extract specific lines to avoid list clutter
Dim rawTitle As String = m.GetDefault("Title", "Untitled")
If rawTitle = "" Then rawTitle = "Untitled"
Dim tLines() As String = Regex.Split("\n", rawTitle)
Dim rawBody As String = m.GetDefault("Body", "")
Dim bLines() As String = Regex.Split("\n", rawBody)
Dim bodySnippet As String = ""
If bLines.Length > 0 Then
bodySnippet = bLines(0)
If bLines.Length > 1 Then bodySnippet = bodySnippet & CRLF & bLines(1)
End If
' Title
Dim lblT As Label : lblT.Initialize("")
lblT.SingleLine = True ' Strictly one line horizontally
Dim xlblT As B4XView = lblT
xlblT.Text = tLines(0)
xlblT.Font = xui.CreateDefaultBoldFont(16)
xlblT.TextColor = 0xFF212121
card.AddView(xlblT, 15dip, 12dip, Root.Width - 60dip, 25dip)
' Preview snippet
Dim lblP As Label : lblP.Initialize("")
Dim xlblP As B4XView = lblP
xlblP.Text = bodySnippet
xlblP.Font = xui.CreateDefaultFont(14)
xlblP.TextColor = 0xFF757575
card.AddView(xlblP, 15dip, 40dip, Root.Width - 60dip, 40dip)
pnlContent.AddView(card, 10dip, TopPos, Root.Width - 20dip, 90dip)
card.SetColorAndBorder(xui.Color_White, 0, 0, 8dip)
UIEffects.SetRectangleRipple(card)
TopPos = TopPos + 100dip
Next
pnlContent.Height = TopPos + 20dip
End Sub
Private Sub OpenEditor(Index As Int)
CurrentIndex = Index
If Index = -1 Then
etTitle.Text = ""
etBody.Text = ""
Else
Dim m As Map = NotesList.Get(Index)
etTitle.Text = m.Get("Title")
etBody.Text = m.Get("Body")
End If
UpdateEditorLayout
pnlEditor.Visible = True
' Focus title if new note, otherwise body
If Index = -1 Then
etTitle.RequestFocus : kb.ShowKeyboard(etTitle)
End If
End Sub
Private Sub kb_HeightChanged (NewHeight As Int, OldHeight As Int)
If pnlEditor.IsInitialized And pnlEditor.Visible Then
' Adjust ScrollView height to the visible area above the keyboard
' We subtract 60dip which is the height of the editor's top toolbar
svEditor.Height = Max(0, NewHeight - 60dip)
UpdateEditorLayout
End If
End Sub
Private Sub etBody_FocusChanged (HasFocus As Boolean)
End Sub
Private Sub UpdateEditorLayout
Dim su As StringUtils
' Measure height needed for the title text given its current width
Dim h As Int = su.MeasureMultilineTextHeight(etTitle, etTitle.Text & " W")
' Set Title height (no need to cap height now that it's in the ScrollView)
etTitle.Height = Max(50dip, h + 10dip)
' Use Top Padding to offset the text relative to the Title
Dim paddingTop As Int = etTitle.Height + 5dip
etBody.Padding = Array As Int(2dip, paddingTop, 2dip, 2dip)
' Measure the height of the actual text
Dim hB As Int = su.MeasureMultilineTextHeight(etBody, etBody.Text & " W")
' Use the current height of the scrollview (which is updated by kb_HeightChanged)
Dim svEditorVisibleHeight As Int = svEditor.Height
' Set inner panel height to at least the visible scroll area, or larger if content demands it
pnlEditorInner.Height = Max(svEditorVisibleHeight, paddingTop + hB + 20dip)
' Stretch the Body view to cover the entire scrollable area
etBody.Height = pnlEditorInner.Height - etBody.Top
End Sub
''''' Event Handlers '''''
Private Sub btnFAB_Click
OpenEditor(-1)
End Sub
Private Sub NoteCard_Click
Dim p As B4XView = Sender
OpenEditor(p.Tag)
End Sub
Private Sub etTitle_TextChanged (Old As String, New As String)
UpdateEditorLayout
End Sub
Private Sub etBody_TextChanged (Old As String, New As String)
UpdateEditorLayout
End Sub
Private Sub btnSave_Click
Dim title As String = etTitle.Text.Trim
Dim body As String = etBody.Text.Trim
kb.HideKeyboard
If title = "" And body = "" Then
pnlEditor.Visible = False
Return
End If
Dim m As Map
If CurrentIndex = -1 Then
m.Initialize
NotesList.InsertAt(0, m) ' Newest first
Else
m = NotesList.Get(CurrentIndex)
End If
m.Put("Title", title)
m.Put("Body", body)
m.Put("Time", DateTime.Now)
SaveNotes
RefreshNoteRows
pnlEditor.Visible = False
End Sub
Private Sub btnDelete_Click
kb.HideKeyboard
If CurrentIndex > -1 Then
NotesList.RemoveAt(CurrentIndex)
SaveNotes
RefreshNoteRows
End If
pnlEditor.Visible = False
End Sub
''''' Data Persistence '''''
Private Sub SaveNotes
Dim jgen As JSONGenerator
jgen.Initialize2(NotesList)
File.WriteString(xui.DefaultFolder, FILE_NAME, jgen.ToString)
End Sub
Private Sub LoadNotes
NotesList.Initialize
If File.Exists(xui.DefaultFolder, FILE_NAME) Then
Try
Dim parser As JSONParser
parser.Initialize(File.ReadString(xui.DefaultFolder, FILE_NAME))
NotesList = parser.NextArray
Catch
Log("Error loading notes: " & LastException)
End Try
End If
End Sub