Android Question B4A_MiniSearchView (With an improvement made by me)

Sergio Haurat

Active Member
Licensed User
Longtime User
Original Post: https://www.b4x.com/android/forum/threads/b4x-xui-minisearchview-autocomplete-field.93564/

In the application I'm developing, I need an event to be executed to capture the text.

Line 2 and lines 84 to 86, within the Sub CLV_ItemClick, you can see the modifications of the MiniSearchView file.

Event declaration:
#Event: TextSelected(Text as String)

New code:
If SubExists(mCallBack, mEventName & "_TextSelected") Then
    CallSubDelayed2(mCallBack, mEventName & "_TextSelected", TextField.Text)
End If

1688879864468.png


I would like to know if someone with experience can help me create the Sub SetItems2, the Items parameter should be Map

Tnx
 

Mahares

Expert
Licensed User
Longtime User
etItems2, the Items parameter should be Map
Instead of modifying the MiniSearchView class, why don;t you convert your map to a list and use that list to set the items. Something like this:
B4X:
Dim mp As Map
    mp.Initialize
    mp.Put("erel","israel")
    mp.Put("klaus","switzerland")
    mp.Put("manfred","germany")
    mp.Put("mangojack","australia")
    mp.Put("johan","south africa")
    mp.Put("peter","england")
    Dim l As List
    l.Initialize
    For Each k As String In mp.Keys
        l.Add(k & "," & mp.Get(k))
    Next
    Members.SetItems(l)
Then you can use Regex,split to separate the key from the value or use them both. If this is not what you want to do, then either post a small project with your map and what you want to accomplish or ditch this solution.
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
Instead of modifying the MiniSearchView class, why don;t you convert your map to a list and use that list to set the items. Something like this:
B4X:
Dim mp As Map
    mp.Initialize
    mp.Put("erel","israel")
    mp.Put("klaus","switzerland")
    mp.Put("manfred","germany")
    mp.Put("mangojack","australia")
    mp.Put("johan","south africa")
    mp.Put("peter","england")
    Dim l As List
    l.Initialize
    For Each k As String In mp.Keys
        l.Add(k & "," & mp.Get(k))
    Next
    Members.SetItems(l)
Then you can use Regex,split to separate the key from the value or use them both. If this is not what you want to do, then either post a small project with your map and what you want to accomplish or ditch this solution.

Hi @Mahares, thank you for your answer. English is not my language, I apologize if something is not grammatically correct.

I should be more explicit about what the purpose of this modification

I already searched in the forum for some way to simulate the ComboBox that exists in Visual Basic .NET. For those who are not familiar, below is an example.
Example combobox Visual Basic .NET:
Private adm_items_opr As DataTable
Dim strSQL As String
strSQL = "select"
strSQL &= " adm_lst_items_opr._id AS adm_lst_items_opr_id,"
strSQL &= " adm_lst_items_opr._desc AS adm_lst_items_opr_desc"
strSQL &= " FROM"
strSQL &= " adm_lst_items_opr"
strSQL &= " ORDER BY"
strSQL &= " adm_lst_items_opr._desc"
adm_lst_items_opr = New DataTable
'Connect to the database
MySQLCmdInterSys.CommandText = strSQL
MySQLDAInterSys.SelectCommand = MySQLCmdInterSys
MySQLDAInterSys.Fill(adm_lst_items_opr)
'Fill the combobox with the result of the query
Me.cmn_leg_ref_tipo_item.DataSource = adm_lst_items_opr
'Defines which value will be displayed by the user
Me.cmn_leg_ref_tipo_item.DisplayMember = "adm_lst_items_opr_desc"
'Defines the value that will be returned when an element of the combo is selected
Me.cmn_leg_ref_tipo_item.ValueMember = "adm_lst_items_opr_id"

Basically, I want to make a new event called "SetItems2", with the parameter type Map to simulate the same object as in Visual Basic .NET.

I know that I can create a Map variable and then look for the description as Key and the ID as value but it is not optimal.

Another difficulty I find is that the current ComboBox B4X does not allow editing and searching. I have a list of more than 800 lines and if I ask the user to search for a record in M, for example, the user will have to do a lot of finger movements doing the upward action.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
I already searched in the forum for some way to simulate the ComboBox that exists in Visual Basic .NET
Maybe you should deviate from thinking about VB.net combobox too much and think about how to accomplish what you want in B4X. Forget B4XCombobox, forget MiniSearchView. Have you looked at B4XSearchTemplate. You can load the template with the resultset of your query. It has a search box where the user can type any characters in the box and close in on his item without what you call: 'finger movements doing the upward action'. If you are still intent on having a new SetItem2, then I hope someone will get back to you.
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
I'm going to try to do it with B4XSearchTemplate. soon I will give you news

Thanks for your time and patience.
@Mahares,

I have seen several examples and it is what I need. I just don't quite understand how to make it work in a B4XFloatTextField without using the B4XDialog.

What I need is that when receiving the focus in the text box (B4XFloatTextField) show the list to select one of the records and replace the text with the selected item.

If you are able to do a simple example, then I'll take care of migrating to what I'm developing.

I have a lot of confusion because "my thinking" is always looking at B4X as Visual Basic .NET
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
how to make it work in a B4XFloatTextField without using the B4XDialog.
At this moment, I am not sure how to make it work without the B4XDialog. I will take a look any way when I get time. The B4XSearchTemplate internal layout is a layout that is composed of a B4XFloatTextField and a xCustomListView. If we cannot do away with the B4XDialog, pehaps using a B4XFloatTextField in combination with a xCustomListview could be a good replacement. There are examples in the forum of using xClv and B4XFloat to closing on a search. In the meantime, someone else may have some ideas and may intervene to help.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
The code below has a B4XFloatingTextField1. When it gets focus it shows a B4XSearchField placed on top of it.
When the dialog closes the result is put in B4XFloatingTextField1.Text, which can then be edited.
You'll have to tweak it for your situation.

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private B4XFloatTextField1 As B4XFloatTextField
    Private listOfKeys As List
    Private dummyFocus As Button
    Private busy As Boolean        'to prevent text field from gaining focus automatically
End Sub

Public Sub Initialize
    dummyFocus.Initialize("")
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.AddView(dummyFocus, -100, -100, 20, 20)
    Root.LoadLayout("MainPage")
    Dim terms As String = $"
Adventures
Alice
Antipathies
Australia
Carroll
Dinah
DRINK
Latitude
Lewis
Longitude
MARMALADE
ORANGE
Rabbit
White
Wonderland
Zealand
    "$
    listOfKeys.Initialize
    Dim lines() As String = Regex.Split(CRLF, terms)
    For Each s As String In lines
        If s.Trim.Length > 0 Then listOfKeys.Add(s)
    Next
End Sub

Private Sub B4XFloatTextField1_FocusChanged (HasFocus As Boolean)
    If busy = True Then
        busy = False
        Return
    End If
    If HasFocus Then
        Search
    Else
        busy = False
    End If
End Sub

Private Sub B4XFloatTextField1_EnterPressed
    busy = False
    'do other stuff
End Sub

Public Sub Search
    Wait For (displaySearch) Complete (Selection As String)
    If Selection.Length > 0 Then
        busy = True
        B4XFloatTextField1.RequestFocusAndShowKeyboard
        B4XFloatTextField1.Text = Selection
        Sleep(10)
        'B4XFloatTextField1.TextField.SelectAll
        'or
        B4XFloatTextField1.TextField.SetSelection(Selection.Length, 0)
    End If
End Sub

Private Sub displaySearch As ResumableSub
    Dim dia As B4XDialog
    dia.Initialize(Root)
    Dim srch As B4XSearchTemplate
    srch.Initialize
    Dim lst As B4XListTemplate
    lst.Initialize
    Dim TextColor As Int = 0xFF5B5B5B
    
    dia.PutAtTop = True
    dia.BlurBackground = False
    dia.OverlayColor = xui.Color_Transparent
    dia.TitleBarColor = 0xFF0092BB
    dia.TitleBarHeight = 50dip
    dia.BackgroundColor = xui.Color_White
    dia.ButtonsColor = xui.Color_White
    dia.ButtonsTextColor = dia.TitleBarColor
    dia.ButtonsHeight = 40
    dia.BorderWidth = 1
    dia.BorderColor = xui.Color_Black
    dia.BorderCornersRadius = 5dip

    srch.CustomListView1.GetBase.Visible = False
    srch.SearchField.TextField.TextColor = TextColor
    srch.CustomListView1.DefaultTextBackgroundColor = xui.Color_White
    srch.CustomListView1.DefaultTextColor = TextColor
    srch.CustomListView1.sv.ScrollViewInnerPanel.Color = 0xFF9C9C9C
    srch.ItemHightlightColor = 0xFF00C5FF
    srch.SetItems(listOfKeys)
    srch.SearchField.HintText = ""
    srch.SearchField.Update
    srch.Resize(B4XFloatTextField1.mBase.width, 400dip)
    Dim sf As Object = dia.ShowTemplate(srch, "", "", "Cancel")
    Sleep(100)
    dia.Base.Top = B4XFloatTextField1.mBase.top
    dia.Base.Left = B4XFloatTextField1.mBase.left
    srch.CustomListView1.GetBase.Visible = True
    srch.SearchField.text = "?"
    srch.SearchField.TextField.SelectAll
    Wait For (sf) Complete (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Return srch.SelectedItem
    Else
        Return ""
    End If
End Sub
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
The code below has a B4XFloatingTextField1. When it gets focus it shows a B4XSearchField placed on top of it.
When the dialog closes the result is put in B4XFloatingTextField1.Text, which can then be edited.
You'll have to tweak it for your situation.

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private B4XFloatTextField1 As B4XFloatTextField
    Private listOfKeys As List
    Private dummyFocus As Button
    Private busy As Boolean        'to prevent text field from gaining focus automatically
End Sub

Public Sub Initialize
    dummyFocus.Initialize("")
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.AddView(dummyFocus, -100, -100, 20, 20)
    Root.LoadLayout("MainPage")
    Dim terms As String = $"
Adventures
Alice
Antipathies
Australia
Carroll
Dinah
DRINK
Latitude
Lewis
Longitude
MARMALADE
ORANGE
Rabbit
White
Wonderland
Zealand
    "$
    listOfKeys.Initialize
    Dim lines() As String = Regex.Split(CRLF, terms)
    For Each s As String In lines
        If s.Trim.Length > 0 Then listOfKeys.Add(s)
    Next
End Sub

Private Sub B4XFloatTextField1_FocusChanged (HasFocus As Boolean)
    If busy = True Then
        busy = False
        Return
    End If
    If HasFocus Then
        Search
    Else
        busy = False
    End If
End Sub

Private Sub B4XFloatTextField1_EnterPressed
    busy = False
    'do other stuff
End Sub

Public Sub Search
    Wait For (displaySearch) Complete (Selection As String)
    If Selection.Length > 0 Then
        busy = True
        B4XFloatTextField1.RequestFocusAndShowKeyboard
        B4XFloatTextField1.Text = Selection
        Sleep(10)
        'B4XFloatTextField1.TextField.SelectAll
        'or
        B4XFloatTextField1.TextField.SetSelection(Selection.Length, 0)
    End If
End Sub

Private Sub displaySearch As ResumableSub
    Dim dia As B4XDialog
    dia.Initialize(Root)
    Dim srch As B4XSearchTemplate
    srch.Initialize
    Dim lst As B4XListTemplate
    lst.Initialize
    Dim TextColor As Int = 0xFF5B5B5B
  
    dia.PutAtTop = True
    dia.BlurBackground = False
    dia.OverlayColor = xui.Color_Transparent
    dia.TitleBarColor = 0xFF0092BB
    dia.TitleBarHeight = 50dip
    dia.BackgroundColor = xui.Color_White
    dia.ButtonsColor = xui.Color_White
    dia.ButtonsTextColor = dia.TitleBarColor
    dia.ButtonsHeight = 40
    dia.BorderWidth = 1
    dia.BorderColor = xui.Color_Black
    dia.BorderCornersRadius = 5dip

    srch.CustomListView1.GetBase.Visible = False
    srch.SearchField.TextField.TextColor = TextColor
    srch.CustomListView1.DefaultTextBackgroundColor = xui.Color_White
    srch.CustomListView1.DefaultTextColor = TextColor
    srch.CustomListView1.sv.ScrollViewInnerPanel.Color = 0xFF9C9C9C
    srch.ItemHightlightColor = 0xFF00C5FF
    srch.SetItems(listOfKeys)
    srch.SearchField.HintText = ""
    srch.SearchField.Update
    srch.Resize(B4XFloatTextField1.mBase.width, 400dip)
    Dim sf As Object = dia.ShowTemplate(srch, "", "", "Cancel")
    Sleep(100)
    dia.Base.Top = B4XFloatTextField1.mBase.top
    dia.Base.Left = B4XFloatTextField1.mBase.left
    srch.CustomListView1.GetBase.Visible = True
    srch.SearchField.text = "?"
    srch.SearchField.TextField.SelectAll
    Wait For (sf) Complete (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        Return srch.SelectedItem
    Else
        Return ""
    End If
End Sub
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
Hello @William Lancee, nice to chat with you. Thanks to people like you and @Mahares among many others, I have learned a lot by reading on the forum.

I'm analyzing the code you made as an example*. I see that B4XDialog appears and you configure some properties to "hide" it. I can't understand, and I sincerely apologize, why it is necessary to use a dialog box and embed the text box component inside it and then perform the search when it gains focus. One problem with this is that the click event doesn't exist, so if I want to make changes because I made a mistake, it doesn't display the search again since the focus is active on the text box component.

Mahares, in the post above, advises me to try integrating it into a CustomView, something I was trying unsuccessfully until they responded.

I'm just trying to duplicate what you see in Image 1.

Basically, I have a table with two fields, _id and _desc (I think I can use Map to populate the data instead of List to preserve the actual code of each record). In Image 2, there is data from a MySQL.

P.S.: I'm attaching this project in case it's useful to another user.

Image 1 (web site, PHP & JavaScript)
Captura de pantalla 2023-07-11 201508.png


Image 2
navicat Captura de pantalla 2023-07-11 201832.png
 

Attachments

  • Testing.zip
    20.6 KB · Views: 144
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
You can certainly add a click event (with a overlayed transparent view) but how does the user know the difference between editing the field and starting a new search?

edit: See below
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
The dialog with the search template is a popup, so it closes automatically when an item is selected.
Therefore you need a recipient B4XFloatTextField for the result.

I changed to code to trigger the search dialogue on text changes in B4XFloatTextField1 as well as on getting focus on B4XFloatTextField1.
It works but still feels a little like a work around.

The B4XComboBox does not do searches and autocomplete.
To write your own search and autocomplete is a major undertaking.
The MiniSearchView has an horizontal CLV. I tried to change it to vertical, but I couldn't get that to work.

Does anyone know how to change the alignment on a B4XSearchTemplate?
 

Attachments

  • testDD_V2.zip
    15.1 KB · Views: 147
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
@William Lancee,

The behavior is very strange in your project; I type in the text box, it opens the options, but when I select one, it writes in the text box and shows the options again.

I'm attaching the project I'm working on to simulate the functionality in Visual Basic .NET. Everything is still experimental o_O, and nothing is working yet. I'm learning using the forum. For example, I still don't know how to add my own parameters to see them in the designer (image 1). In Visual Basic .NET, it's done using "Property Get/Set" as shown below.

Image 1
1689136856129.png


Property Get/Set Visual Basic .NET:
Class Class1
    ' Define a local variable to store the property value.
    Private propertyValue As String
    ' Define the property.
    Public Property Prop1() As String
        Get
            ' The Get property procedure is called when the value
            ' of a property is retrieved.
            Return propertyValue
        End Get
        Set(ByVal value As String)
            ' The Set property procedure is called when the value
            ' of a property is modified.  The value to be assigned
            ' is passed in the argument to Set.
            propertyValue = value
        End Set
    End Property
End Class

The code adapted to B4A would be as follows.

Code simulation:
Dim strVariable As String
Dim FakeClass As Class1
Class1.Prop1 = "Testing 123" 'Set new value to Prop1
strVariable = Class1.Prop1 'Set strVariable getting Prop1 value
 

Attachments

  • ComboBoxCloneNet.zip
    136.4 KB · Views: 154
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
I think we are on a diverting course.
You're modifying an existing view to simulate VB.Net behavior.
I'm using the existing facilities of B4X to implement a functionality you need.

I tested the testDD_2 in post #11 on B4A and B4J (make sure you have the latest). It functions as required.
The behavior you see is not strange. It just means that the popup is triggered when you don't want it.
You want it when the target view gets focus and when the target view is edited and the text is changed.
This requires a global 'busy' switch to avoid false triggers. Originally I tested it on B4J (my preferred testing environment).
On B4A, the event sequence is slightly different, and false triggers occurred. I fixed it in testDD_V2.

Now about a completely different problem. Modifying an existing view is not easy
There is a Booklet 'CustomViews' in the Learn->Guides link on top of this page to show you how to add properties to custom views.
As @Mahares inferred, it is a folly to apply expectations of one computer language to another.
B4X is a multiplatform language. VB.Net is not. The native views/controls available and the corresponding events are different on each platform.
This is determined by the operating system, not the computer language used.

Your efforts to modify MiniSearchView show courage in learning, and maybe you should continue.
To help debug what you have so far, is beyond my scope on this forum, and probably others too.
As in all debugging, use break points, try different things, read the manuals, and yes ask the Forum when you're stuck.
But ask only isolated snippets, with simplified examples, in code tags or attached zip files.

I looked at your code and I would have to spend a week trying figure it out. There may be others who could do better then I.
 
Last edited:
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
Thanks for your time and effort. I am trying other methods to achieve what I need. I'm going to close this post and if I get a result close to what I need. I'm going to analyze if I haven't downloaded the wrong version of your code.

Thank you so much
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Where do I find that example?
I think this is the link you are looking for.
It is supposed to be a code snippet, but I do not see any code.
Do not give up so soon. Can you post a csv file of the data you show in post #9 ( not a screenshot) so I can take a look, import to a SQLite database and see if I can get you a search using a B4XFloatTextField and an xClv without using the B4XDialog.
 
Upvote 0

Sergio Haurat

Active Member
Licensed User
Longtime User
I think this is the link you are looking for.
It is supposed to be a code snippet, but I do not see any code.
Do not give up so soon. Can you post a csv file of the data you show in post #9 ( not a screenshot) so I can take a look, import to a SQLite database and see if I can get you a search using a B4XFloatTextField and an xClv without using the B4XDialog.
File csv in zip file. I don't know what xClv is, I'm sorry
 

Attachments

  • cmn_lst_clientes.zip
    11.6 KB · Views: 217
Upvote 0
Top