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

Android Question [SOLVED] Strange behavior trying to remove multiple items on a xCustomListView

Discussion in 'Android Questions' started by Alejandro Moyano, Aug 5, 2019.

  1. Alejandro Moyano

    Alejandro Moyano Member Licensed User

    Hi im trying to remove multiple items with clv.RemoveAt(index) but works a bit odd, sometimes delete 2 items of 3, others 1 of 3.
    Am i doing it right?

    Screenshot_2019-08-05-15-52-47.png Screenshot_2019-08-05-15-53-01.png

    Code:
    Sub Class_Globals
        
    Private xui As XUI
        
    Private vActivity As B4XView
        
    Private vCodProducto As Int
        
    Private lblNombreProducto, lblConIva, lblSinIVA As Label
        
    Private txtCantidad As B4XView
        
    Type ItemPedido (vCodProducto As Int,txtCantidad As B4XView,lblNombreProducto As Label, lblConIva As Label, lblSinIVA As Label)
        
    Private clvProductos As CustomListView
        
    Private vSelectedItems As List
        
    Private vBaseColor, vSelectedColor As Int
    End Sub

    'Initializes the object. You can add parameters to this method if needed.
    Public Sub Initialize(activity As B4XView)
        vActivity = 
    activity
        vActivity.RemoveAllViews
        vActivity.LoadLayout(
    "frmNuevoPedido")
        vSelectedItems.Initialize
        vBaseColor = 
    0xFFA8CDAA
        vSelectedColor = 
    0xFF0686CC
        CargarPedido
    End Sub

    Private Sub CargarPedido
        
    For i = 1 To 50
            
    Dim icp As ItemPedido
            icp.Initialize
            clvProductos.Add(CrearItemProducto(i,
    "Hola"&i,i*1000,i*1000*1.21,i,icp),icp)
        
    Next
    End Sub

    Private Sub CrearItemProducto(codigo As Int,nombre As String,precio_sin_iva As String, precio_con_iva As String, cantidad As Int, icp As ItemPedido) As B4XView
        
    Dim item As B4XView = xui.CreatePanel("")
        item.SetLayoutAnimated(
    0,0,0,clvProductos.GetBase.Width,85dip)
        item.LoadLayout(
    "ItemPedido")
        vCodProducto = codigo
        lblNombreProducto.Text = nombre
        lblConIva.Text = precio_con_iva
        lblSinIVA.Text = precio_sin_iva
        txtCantidad.Text = cantidad
        txtCantidad.Color = xui.Color_Transparent
        icp.lblConIva = lblConIva
        icp.lblSinIVA = lblSinIVA
        icp.lblNombreProducto = lblNombreProducto
        icp.vCodProducto = vCodProducto
        
    Return item
    End Sub

    Sub cmdMenu_Click
        
    #if B4A
        
    StartActivity(Menu)
        
    #end if
    End Sub

    Sub cmdExit_Click
        
    #If B4A
        CallSubDelayed(Main,
    "CloseMe")
        
    #End If
    End Sub


    Sub cmdEditClient_Click
        
    'mesaje con input
    End Sub

    Sub cmdFinalizar_Click
        
    End Sub

    'Delete all selected items
    Sub cmdEliminar_Click
        
    For Each i In vSelectedItems
            
    Log(i)
            clvProductos.RemoveAt(i)
        
    Next
        vSelectedItems.Clear
    End Sub

    Sub cmdAnadir_Click
        
    End Sub

    'This function handle the painting and selection of items.
    Sub clvProductos_ItemClick (Index As Int, Value As Object)
        
    If vSelectedItems.IndexOf(Index) <> -1 Then
            clvProductos.GetPanel(Index).Color = vBaseColor
            vSelectedItems.RemoveAt(vSelectedItems.IndexOf(Index))
        
    Else
            vSelectedItems.Add(Index)
            clvProductos.GetPanel(Index).Color = vSelectedColor
        
    End If
    End Sub
     
  2. Jorge M A

    Jorge M A Active Member Licensed User

    Probably not.
    Maybe you are confusing your label (1,2,3,4...) with the index.
    Every time you remove an item, both the size and the indexes of the lists are recalculated, so that if you remove the index 2, which was before the 3, becomes 2.
    You have to look for the way to "mark" the selected ones to eliminate, and look for the new index assigned to erase it with its new position, with each removal.
     
  3. Alejandro Moyano

    Alejandro Moyano Member Licensed User

    TXS @Jorge M A seems i don't considerate the recalculated index, i solved doing this:

    Code:
    Sub Class_Globals
        
    Private xui As XUI
        
    Private vActivity As B4XView
        
    Private vCodProducto As Int
        
    Private lblNombreProducto, lblConIva, lblSinIVA As Label
        
    Private txtCantidad As B4XView
        
    Type ItemPedido (vCodProducto As Int,txtCantidad As B4XView,lblNombreProducto As Label, lblConIva As Label, lblSinIVA As Label)
        
    Private clvProductos As CustomListView
        
    Private vSelectedProductCodes As List
        
    Private vBaseColor, vSelectedColor As Int
    End Sub

    'Initializes the object. You can add parameters to this method if needed.
    Public Sub Initialize(activity As B4XView)
        vActivity = 
    activity
        vActivity.RemoveAllViews
        vActivity.LoadLayout(
    "frmNuevoPedido")
        vSelectedProductCodes.Initialize
        vBaseColor = 
    0xFFA8CDAA
        vSelectedColor = 
    0xFF0686CC
        CargarPedido
    End Sub

    Private Sub CargarPedido
        
    For i = 1 To 50
            
    Dim icp As ItemPedido
            icp.Initialize
            clvProductos.Add(CrearItemProducto(i,
    "Hola"&i,i*1000,i*1000*1.21,i,icp),icp)
        
    Next
    End Sub

    Private Sub CrearItemProducto(codigo As Int,nombre As String,precio_sin_iva As String, precio_con_iva As String, cantidad As Int, icp As ItemPedido) As B4XView
        
    Dim item As B4XView = xui.CreatePanel("")
        item.SetLayoutAnimated(
    0,0,0,clvProductos.GetBase.Width,85dip)
        item.LoadLayout(
    "ItemPedido")
        vCodProducto = codigo
        lblNombreProducto.Text = nombre
        lblConIva.Text = precio_con_iva
        lblSinIVA.Text = precio_sin_iva
        txtCantidad.Text = cantidad
        txtCantidad.Color = xui.Color_Transparent
        icp.lblConIva = lblConIva
        icp.lblSinIVA = lblSinIVA
        icp.lblNombreProducto = lblNombreProducto
        icp.vCodProducto = vCodProducto
        
    Return item
    End Sub

    Sub cmdMenu_Click
        
    #if B4A
        
    StartActivity(Menu)
        
    #end if
    End Sub

    Sub cmdExit_Click
        
    #If B4A
        CallSubDelayed(Main,
    "CloseMe")
        
    #End If
    End Sub


    Sub cmdEditClient_Click
        
    'mesaje con input
    End Sub

    Sub cmdFinalizar_Click
        
    End Sub

    'Delete all selected items
    Sub cmdEliminar_Click
        
    For Each i In vSelectedProductCodes
            DeleteItemByCode(i)
        
    Next
        vSelectedProductCodes.Clear
    End Sub

    Sub cmdAnadir_Click
        
    End Sub

    'Delete an item
    Private Sub DeleteItemByCode(code As Int)
        
    For i = 0 To clvProductos.Size-1
            
    Dim icp As ItemPedido = clvProductos.GetValue(i)
            
    If icp.vCodProducto = code Then
                clvProductos.RemoveAt(i)
                
    Exit
            
    End If
        
    Next
    End Sub

    'This function handle the painting and selection of items.
    Sub clvProductos_ItemClick (Index As Int, Value As Object)
        
    Dim item_pedido As ItemPedido = Value
        
    If vSelectedProductCodes.IndexOf(item_pedido.vCodProducto) <> -1 Then
            clvProductos.GetPanel(Index).Color = vBaseColor
            vSelectedProductCodes.RemoveAt(item_pedido.vCodProducto)
        
    Else
            vSelectedProductCodes.Add(item_pedido.vCodProducto)
            clvProductos.GetPanel(Index).Color = vSelectedColor
        
    End If
    End Sub
    Plus, it allow me delete a product directly by product code.. the only noise is that is not efficient.. but i figure that the user never will have a list with more than 15 productos.
     
  4. sorex

    sorex Expert Licensed User

    just go backwards through your selected items list (if that list is correctly sorted) and delete the items.

    the shifting won't affect your routine since you will look up items for deletion earlier in the list than where the shifting happend.
     
    emexes and Alejandro Moyano like this.
  5. Alejandro Moyano

    Alejandro Moyano Member Licensed User

    Txs @sorex i felt a bit dump asking about it.. seems so obvious now.
     
  6. emexes

    emexes Well-Known Member Licensed User

    Minor thought: while you're in the land of O(n), is it worth searching the whole list just in case there are multiple items with .vCodProducto = code?

    Yeah, it'll double your search time (presumably from negligible to negligible) but could save you heaps of debugging time if it ever occurs. Not that I've ever experienced such issues myself... ;-)

    Perhaps even better: keep a count of how many items are deleted, and log if anything other than 1.
     
    Last edited: Aug 7, 2019
    Shelby likes this.
  7. emexes

    emexes Well-Known Member Licensed User

    lol
     
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