Android Code Snippet SD: Spinner with CustomView

I've created a new class with CistomView to have the same features on the spinner object as ListView. A second line of text and the ability to add an image beside each item.

Also there is the ability to put the screen in gray when you click on the spinner. And finally, the ability to represent each item with rounded edges. In the cases there is an image that will also be rounded.

Hope it may be useful to you

Proprietes
Enabled As Boolean
SelectedItem As String
SelectedID As String
SelectedIndex As String
GrayDisplay As Boolean ' If Make Screeen gray when click (Set/Get)
BColor As Int ' BackgroundColor of Spinner's Label (Get/Set)
TColor As Int ' TextColor of Spinner's Label (Get/Set)
HintColor As Int ' TextColor of Spinner's Hint (Get/Set)
RoundCorner As Boolean
If the spinner opens in an anomalous position:
Set these prorpietes (left e Top) to set the screen position of the spinner's aperture on the screen.
For this reason we do not recommend inserting the spinner inside a scrollView because it has problems calculating its opening, or setting the position from code using left and top

Left As Int
Top As Int

Method
Initialize (vCallback As Object, vEventName As String)
Add(Text As String, TextHelp As String,ID As String, BackgroundColor As Int, TextColor As Int, Gravities As Int,Image As Bitmap)
' Add Single element
AddAll(L As List, TextHelp As String, BackgroundColor As Int, TextColor As Int, Gravities As Int)
' Add a List
Size as int ' return number of elements
Clear ' Clear all elements
RemoveIndex(Position As Int) ' Remove element at Index
RemoveID(ID As String) ' Remove element from ID
GetItem(Position As Int) As String ' Get Value from position/index
GetItemFromID(ID As String) As String ' Get Value from ID
GetID(Position As Int) As String ' Get ID at position/index
SetIndex(Position As Int) ' Set selected from position/index
SetID(Id As String) ' Set selected from ID
SetBackgroundDrawable(Draw As ColorDrawable) ' Set Background with colordrawable
SetBackgroundImage(Bitmap As Bitmap) ' Set Background with image
SetLabelTextSize(TextSizeLabel As Int) ' Set Text Size of label
Close ' close a ListItem windows
Open ' Apen a ListItem Windows​

Event
ItemClick (Position As Int, Value as String)​

Update 1.02
Screen1.png Screen2.png Screen3.png Screen4.png Screen5.png Screen6.png
 

Attachments

  • SD_Spinner 1.02.zip
    19.7 KB · Views: 1,294
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
The error came on Line 59 of the module SD_Spinner..
It is not possible to understand what happens with the few inflamations that you give.
Debug and see which line the error presents.

Try starting from the attached example

PS. The class is made available with the source code so that every developer can modify it, improve it or correct it.
I do not offer assistance on classes with attached source because every developer is able to intervene directly on the source code and therefore no assistance is required.
 

Star-Dust

Expert
Licensed User
Longtime User
Update, added method

Enabled As Boolean
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
Hello. I have a problem.

If I use:

B4X:
Private Sub CreateClv1Item(item As ClvPedidosItem, Reg As Map) As B4XView
  Dim p As B4XView = xui.createPanel("")
  p.SetLayoutAnimated(0, 0, 0, 100%x, 115dip)
  p.LoadLayout("ClvPedidosItem")
  ...
  ...
  ...
End Sub

To load individual items in a clv, then I get: java.lang.RuntimeException: Object should first be initialized (View) in the p.LoadLayout line.

If I use Activity.LoadLayout("main"), then the SD_Spinner works perfectly.

Any idea?

Thanks.
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
Breaks at:
B4X:
Public Sub DesignerCreateView (Base As Panel, Lbl As Label, Props As Map)
    mBase = Base
    mBase.Tag="SD_SPINNER"
    
    Left=0
    Top=0
    Dim Obj As View = mBase
    Do While Not(GetType(Obj) = "android.widget.FrameLayout")
        Log(Obj.Parent)
        Try
            Left=Left+Obj.Left
            Top=Top+Obj.Top
        Catch
            Log("Errore")
        End Try
        Obj=Obj.Parent
    Loop
    MyAct=Obj
...
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
It does not work because it is within a view that the parent does not find correctly, usually accessing the ScrollView panel.
Replace this:
B4X:
Dim Obj As View = mBase
    Do While Not(GetType(Obj) = "android.widget.FrameLayout")
        Log(Obj.Parent)
        Try
            Left=Left+Obj.Left
            Top=Top+Obj.Top
        Catch
            Log("Errore")
        End Try
        Obj=Obj.Parent
    Loop
    MyAct=Obj

with this
B4X:
Dim r As Reflector
r.Target = r.GetActivityBA
MyAct=r.GetField("vg")
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
It does not work because it is within a view that the parent does not find correctly, usually accessing the ScrollView panel.
Replace this:
B4X:
Dim Obj As View = mBase
    Do While Not(GetType(Obj) = "android.widget.FrameLayout")
        Log(Obj.Parent)
        Try
            Left=Left+Obj.Left
            Top=Top+Obj.Top
        Catch
            Log("Errore")
        End Try
        Obj=Obj.Parent
    Loop
    MyAct=Obj

with this
B4X:
Dim r As Reflector
r.Target = r.GetActivityBA
MyAct=r.GetField("vg")

Perfect!!!

Thank you very much.
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
How can I set the top of spinner options panel depending of the clv selected item?
The left works with next code:

B4X:
private Sub Lab_Click
    Dim I As IME
    I.Initialize("")
    I.HideKeyboard
    Dim labelaux As Label = Sender
    Dim panelaux As Panel = labelaux.Parent
    Left2 = panelaux.Left
    'Left2 = 100%x - panelaux.Width
    Top2 = panelaux.Top + panelaux.Height
    DesignerList
End Sub
 
Last edited:

Star-Dust

Expert
Licensed User
Longtime User
I did not understand the question
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
I did not understand the question
I would like to get the panel with the possible options to be selected from the spinner to be correctly located underneath the SD_Spinner selected at all times as the standard Spinner does.
With the previous piece of code, I get it to be correctly positioned with respect to the horizontal position.
What I need now is to position it vertically depending on the item of the CustomListView in which the SD_Spinner is hosted.
Look at the attached image to see if this way I can explain myself better.
The value of Left2 and Top2 would apply later in the Sub DesignerList
 

Attachments

  • tempFileForShare_20190103-074042.jpg
    tempFileForShare_20190103-074042.jpg
    228.8 KB · Views: 430

Star-Dust

Expert
Licensed User
Longtime User
As you will see in the original code there is the modification of two variables top and left.
That piece of code gives you the error needed to correctly position the spinner in the screen.
having eliminated you can still place it accidental top and left property from the outside and position it correctly.
(Make sure the variables are public and not private)
B4X:
SD_Spinner.Top=myposTop
This change does not change the position of the View but only of the Spinner. to change the position of the view, this would be
B4X:
SD_Spinner.GetBase.Top=myposTop
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
As you will see in the original code there is the modification of two variables top and left.
That piece of code gives you the error needed to correctly position the spinner in the screen.
having eliminated you can still place it accidental top and left property from the outside and position it correctly.
(Make sure the variables are public and not private)
B4X:
SD_Spinner.Top=myposTop
This change does not change the position of the View but only of the Spinner. to change the position of the view, this would be
B4X:
SD_Spinner.GetBase.Top=myposTop

I'm sorry, but I do not understand what you mean.
If I leave the code as it comes from origin, the panel with the different options of the spinner places it in the same vertical position (not the correct one depending on the selected SD_Spinner) and also almost to the left of the whole of the screen.

Hence, I tried to solve it with two new variables that I only apply if necessary

B4X:
Sub DesignerList
...
' Variables para intentar colocar el ListPanel correctamente
        If Left2 <> 0 Then L = Left2
        If Top2 <> 0 Then T = Top2
        AppPanel.AddView(ListPanel,L,T,mBase.Width,h)
...
End Sub
 

Attachments

  • tempFileForShare_20190103-082319.jpg
    tempFileForShare_20190103-082319.jpg
    137.5 KB · Views: 401

Star-Dust

Expert
Licensed User
Longtime User
It is not necessary for you to modify the library from within. But just change some properties of the spinning that I had already entered for this event.

B4X:
Dim Sp as SD_Spinner

Panel.AddView(Sp.GetBase,100dip,10dip,100dip,50dip)
' Coordinate Open Spin
Sp.Top=10Dip
Sp.Left=100Dip
If inserted into the Design
B4X:
Dim Sp as SD_Spinner

Panel.loadLayout("panelWithSpin")
' Coordinate Open Spin
Sp.Top=10Dip
Sp.Left=100Dip
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
It is not necessary for you to modify the library from within. But just change some properties of the spinning that I had already entered for this event.

B4X:
Dim Sp as SD_Spinner

Panel.AddView(Sp.GetBase,100dip,10dip,100dip,50dip)
' Coordinate Open Spin
Sp.Top=10Dip
Sp.Left=100Dip
If inserted into the Design
B4X:
Dim Sp as SD_Spinner

Panel.loadLayout("panelWithSpin")
' Coordinate Open Spin
Sp.Top=10Dip
Sp.Left=100Dip

Could be?

B4X:
sp.GetBase.Top=10dip
sp.GetBase.Left=100dip

Top and left is unreachable in Update 1.0.1 28/09/2017 of SD_Spinner class.
 

Star-Dust

Expert
Licensed User
Longtime User
I already explained in post #52 that you do not have to do SD_Spinner1.GetBase.Top (and left).
Read carefully what I wrote to you.

At the beginning of the class you will find
B4X:
Private Top,Left As Int

you have to change into
B4X:
Public Top,Left As Int
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
I already explained in post #52 that you do not have to do SD_Spinner1.GetBase.Top (and left).
Read carefully what I wrote to you.

At the beginning of the class you will find
B4X:
Private Top,Left As Int

you have to change into
B4X:
Public Top,Left As Int

I
I already explained in post #52 that you do not have to do SD_Spinner1.GetBase.Top (and left).
Read carefully what I wrote to you.

At the beginning of the class you will find
B4X:
Private Top,Left As Int

you have to change into
B4X:
Public Top,Left As Int

Thank you very much for your quick response.
I had already made that change to public.
After doing it I have managed to get the horizontal position correctly, but unfortunately, the vertical position does not adjust it well.
It remains at the top of the screen regardless of the spinner of the clv that you select.

B4X:
Sub FillData
            Dim ClvItem As ClvPedidosItem
            ClvItem.Initialize
            Clv1.Add(CreateClv1Item(ClvItem, Reg), ClvItem)
End Sub


Private Sub CreateClv1Item(item As ClvPedidosItem, Reg As Map) As B4XView
    Dim p As B4XView = xui.createPanel("")
    p.SetLayoutAnimated(0, 0, 0, 100%x, 115dip)
    p.LoadLayout("ClvPedidosItem")
    'p.LoadLayout("PruebaClvSD_Spinner")
    item.LblCliente = LblCliente
    item.LblFecha = LblFecha
    item.CheckBoxAplazado = CheckBoxAplazado
    item.SpinnerOpcionesClv1 = SpinnerOpcionesClv1
    item.SD_SpinnerOpcionesClv1 = SD_SpinnerOpcionesClv1
   
    LblCliente.Text     = "Cliente: " & Reg.Get("Cliente".ToLowerCase)
    LblFecha.Text         = Reg.Get("Fecha".ToLowerCase)
    LblFiscal.Text         = Reg.Get("RazonFiscal".ToLowerCase)
    LblComercial.Text     = Reg.Get("RazonComercial".ToLowerCase)
    LblNApuntes.Text    = Reg.Get("NApuntes".ToLowerCase)
    CheckBoxAplazado.Checked = Reg.Get("Estado".ToLowerCase) = "A"
    CheckBoxAplazado.Enabled = False
   
   
    SD_SpinnerOpcionesClv1.Top=10dip
    SD_SpinnerOpcionesClv1.Left=100dip
    SD_SpinnerOpcionesClv1.Add("Op1","Non so1 lo que tu esperabas", 1,Colors.Black,Colors.White,Gravity.CENTER,Null)
    SD_SpinnerOpcionesClv1.Add("Op2","Non so2", 2,Colors.Black,Colors.White,Gravity.CENTER,Null)
    'SD_SpinnerOpcionesClv1.Left2 = SD_SpinnerOpcionesClv1.GetBase.Left
    SpinnerOpcionesClv1.Add("Opciones:")
    If CheckBoxAplazado.Checked Then
        SpinnerOpcionesClv1.Add("Activar")
    Else
        SpinnerOpcionesClv1.Add("Aplazar")
    End If
    SpinnerOpcionesClv1.Add("Cambiar Fecha")
    SpinnerOpcionesClv1.Add("Cancelar")
    SpinnerOpcionesClv1.SelectedIndex = -1
   
    SpinnerOpcionesClv1.DropdownBackgroundColor = Colors.Green
    SpinnerOpcionesClv1.DropdownTextColor = Colors.Magenta
    SpinnerOpcionesClv1.TextColor = Colors.Red
   
       
    Return p
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
I do not understand the problem well. SD_Spinner is inside a panel or inside what?

I would like to understand all the parents of the spinner until you get to Activity
 

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
I do not understand the problem well. SD_Spinner is inside a panel or inside what?

I would like to understand all the parents of the spinner until you get to Activity

This is a simplyfied example.¡

I hope this helps.
 

Attachments

  • xCustomListView con SD_Spinner.zip
    19.5 KB · Views: 424

Star-Dust

Expert
Licensed User
Longtime User
The problems are different.
The first that the SPINNERs are inside a CustomListView and therefore to calculate the position must know the position of the Y scroll.
Secondly, you have loaded all the SPINNERs with LoadLayout and with the same name SD_Spinner1 and therefore for him it is always the same spinner and he is moving it.

However, I study it above, but I have to change it strongly. As it is, it can not work
 
Last edited:

Gabino A. de la Gala

Well-Known Member
Licensed User
Longtime User
The problems are different.
The first that the SPINNERs are inside a CustomListView and therefore to calculate the position must know the position of the Y scroll.
Secondly, you have loaded all the SPINNERs with LoadLayout and with the same name SD_Spinner1 and therefore for him it is always the same spinner and he is moving it.

However, I study it above, but I have to change it strongly. As it is, it can not work

Could somehow be assigned the panel that you deploy with the options to the panel of the item clicked ?. Thus the positions would be relative to the item, not to of activity.
 

Star-Dust

Expert
Licensed User
Longtime User
The open spinner is hooked to the main activity so you can take full advantage of the screen. It can not be attached to an internal panel, otherwise the dimensions would be limited to the size of the panel.

Anyway in the afternoon I send you the correct code
 
Top