Italian spazio indesiderato alla creazione della customview

Schakalaka

Active Member
Licensed User
Buongiorno,
ho un problema con una custom view.
il codice è stato creato da un utente del forum, per dare un design a grid invece della classica customlistview in colonna, appunto, questo è a due a due.
Problema:
all' aggiunta di un nuovo elemento, in un' altra activity, voglio aggiungere solo quello alla customview esistente, ma in ordine alfabetico.
ci sono vicino, ma all' aggiunta, anche utilizzando clv.clear, mi aggiunge uno spazio prima n volte, quante sono gli elementi della view.
l' esempio di esempio, è esplicativo (forse)
grazie
Video:
 

Attachments

  • CustomCardView test.zip
    21.9 KB · Views: 41
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Buongiorno,
Buonanotte 🤭

Gli do un'occhiata, pur non avendo capito il post :) (intanto, leggere: "in un'altra Activity" non mi piace; passa alle B4XPages, vale assolutamente la pena)

1702330931045.png


(correggere, anche se sono solo warning)
 

Schakalaka

Active Member
Licensed User
eh lo so, sarà l' ora tarda.
comunque ho aggiunto un video al primo post.
il problema si presenta dopo aver aggiunto una nuova categoria.
domani ti potrò dare altre info
 

LucaMs

Expert
Licensed User
Longtime User
Ho capito il problema, non ancora la soluzione. Mi sembra che quella custom view, senza offesa, sia un gran bel casino! Credo sia una xCustomListView modificata male.
Dovresti gestire il Top originale, la LastPanelTop incasina le cose.

Dato che ci ho "perso" già un bel po' di tempo, non lo faccio io ma ti consiglierei di creare una normale classe, passagli una normale xCustomListView, aggiungi alla classe qualche metodo, ad esempio AddForm ("Form" inteso come singola "scheda"), un contatore a livello di modulo che conservi il numero di schede., un metodo per eliminare una scheda, etc.

In ogni Item della xCustomListView caricherai un layout con due Panel (le schede), invisibili; ad ogni AddForm, calcolerai e renderai visibile o meno quello di destra (contatore schede pari o dispari).

Potresti perfino aggiungerci un metodo cui passare la Map di dati che crei tutte le schede.

Al suo interno NON usare valori in percentuale.

Mi pare ci sia anche una custom view di Erel per caricare e gestire immagini su più colonne; probabilmente sarebbe più facile modificare quello, piuttosto che xCustomListView, sostituendo le ImageView (che probabilmente sono B4XImageView) con dei Panel.

[Se quello è tutto il tuo progetto finora, quindi non ampio, sarebbe meglio che lo faccessi di tipo B4XPages]
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Aggiustato. Nel metodo Clear non resettavi LastPanelTop e PanelIsLeft.

Ogni mia modifica l'ho segnata con: 'lm


[Resta valido il suggerimento di farne un progetto B4XPages, se non sei già "troppo" avanti]
 

Attachments

  • CustomCardView test.zip
    22.4 KB · Views: 40
Last edited:

Schakalaka

Active Member
Licensed User
ovviamente sono ancora qua
sto provando senza successo ad ottenere i vari valori del panel.


B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
Log(Panel1.GetView(2).Text)

    
End Sub

cosi restituisce l' ultimo valore e non quello selezionato

B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
    ' Ottieni il pannello corrente dalla vista Sender
    Dim p As B4XView = Sender

    ' Assicurati che l'elemento corrente sia inizializzato
    If p.IsInitialized Then
        ' Accedi all'oggetto interno con indice 2 (o l'indice desiderato) all'interno del pannello corrente
        Dim viewAtIndex2 As B4XView = p.GetView(2)

        ' Assicurati che l'oggetto interno sia inizializzato
        If viewAtIndex2.IsInitialized Then
            ' Adesso puoi fare qualcosa con l'oggetto interno, ad esempio ottenere il testo di un EditText
            Dim editTextContent As String = viewAtIndex2.Text
            Log("Contenuto dell'oggetto interno all'indice 2: " & editTextContent)
        Else
            Log("L'oggetto interno all'indice 2 non è inizializzato.")
        End If
    Else
        Log("Il pannello corrente non è inizializzato.")
    End If

    
End Sub
cosi si interrompe qui " Dim viewAtIndex2 As B4XView = p.GetView(2)"

B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
    Dim v() As Object=Value
    Log(v(0))
    Log(v(1))
    
End Sub

B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
    Dim Index As Int = CvlMovTot.GetItemFromView(Sender)
    Dim pnl As B4XView = CvlMovTot.GetPanel(Index)
    Dim lbl As B4XView = dd.GetViewByName(pnl, "Label1Name_fruit")
    Dim chk As B4XView = dd.GetViewByName(pnl, "Label2Calories")
    Log(lbl.Text)
    Log(chk.Text)
    
End Sub
si interrompe alla prima riga


è sempre massacrante usare queste clv
 

LucaMs

Expert
Licensed User
Longtime User
Hai caricato le view degli item da layout? Se è così (e così andrebbe fatto), guarda l'albero delle view nel Designer, così "saprai l'indice" di ogni view.

In generale, quando hai problemi simili, usa dei Log(GetType(QualcheOggetto)).

Infine, ad ogni item della CLV puoi associare un valore, che può anche essere un oggetto, come sai. A me è sempre sembrata una buona idea creare un custom type con gli N "campi" corrispondenti ai valori delle view, creare un oggetto di questo tipo ed associarlo all'item. In questo modo, nell'evento:

Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)

potresti avere:

Dim V As [tuo custom type] = Value

ed avere tutti i singoli valori:

V.FruitName
V.Calories
etc.


Sono stato troppo sintetico? 🤔
 

Schakalaka

Active Member
Licensed User
Hai caricato le view degli item da layout? Si
panel, imageview, e 6 label

Quindi creo un type custom:

B4X:
Type dettaglitransazione (txtimg As String, txtDescrizione As String,  txtconto As String, txtData As String, txtcategoria As String, txtbeneficiario As String, txtprice As String)
inizializzo il type all' inizio
index = 0 è un panel

nella sub di ricezione dati, abbino i valori del type
B4X:
        dt.txtDescrizione = mov_descrizione
        dt.txtcategoria = mov_categoria
        dt.txtbeneficiario = mov_beneficiario
        dt.txtData = dataString
        dt.txtconto = mov_importo

B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
    
    
    dt = Value
    
    dt.txtDescrizione = Label1Name_fruit.Text

    Log(Label1Name_fruit.Text)


End Sub

così non va
 

Sagenut

Expert
Licensed User
Longtime User
Hai caricato le view degli item da layout? Si
panel, imageview, e 6 label

Quindi creo un type custom:

B4X:
Type dettaglitransazione (txtimg As String, txtDescrizione As String,  txtconto As String, txtData As String, txtcategoria As String, txtbeneficiario As String, txtprice As String)
inizializzo il type all' inizio
index = 0 è un panel

nella sub di ricezione dati, abbino i valori del type
B4X:
        dt.txtDescrizione = mov_descrizione
        dt.txtcategoria = mov_categoria
        dt.txtbeneficiario = mov_beneficiario
        dt.txtData = dataString
        dt.txtconto = mov_importo

B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
  
  
    dt = Value
  
    dt.txtDescrizione = Label1Name_fruit.Text

    Log(Label1Name_fruit.Text)


End Sub

così non va
Quando crei l'item assegnerai il contenuto delle 6 Label anche al Type e poi aggiungerai l'item alla CLV in questo modo
B4X:
CLV.Add(pannelloitem, tuotype)
Cliccando sull'Item della CLV avrai tutto in questo modo
B4X:
Private Sub CvlMovTot_ItemClick (Index As Int, Value As Object)
    dt = Value
    Log(dt.txtDescrizione)
    Log(dt.txtconto)
    Log(dt.txtdata)
End Sub
Anche se non sò cosa tu debba fare esattamente. :)
 

LucaMs

Expert
Licensed User
Longtime User
Bisogna chiarire bene termini ed oggetti (e memorizzarli).

Tu dichiari un nuovo tipo di dato, così come Int, String, etc sono tipi di dati.
B4X:
Type tPersona(Nome As String, Cognome As String, Eta As Int)

L'Editor ti aiuta a creare una funzione che restituisce un nuovo oggetto di tipo tPersona, oggetto cui tu ti riferirai tramite una variabile. Un po' come 123 fosse un oggetto di tipo Int; per usarlo non è che lo scrivi a vanvAra (cit.), hai una variabile che "contiene" quel 123 (con le variabili oggetto la cosa dietro le quinte è diversa, la variabile non contiene l'oggetto, ha un riferimento alla zona di memoria in cui è "scritto" quell'oggetto, come se Peso puntasse a 123).

Quando dovrai creare un nuovo oggetto di tipo tPersona, conviene usare la funzione generata dall'editor (non è obbligatorio, nemmeno avere quella funzione).
B4X:
Dim Persona1 As tPersona = CreatetPersona("Ugo", "Persichetti", 45)
Dim Persona2 As tPersona = CreatetPersona("FrENGO", "TreTre", 55)

Ora, potresti avere una clvPersone. Crei un item fisico - il panel in cui carichi il layout - e gli associ Persona1:

clvPersone.Add(CreateItem(....), Persona1)

Nell'evento click della clvPersone:
B4X:
Private Sub clsPersone_ItemClick (Index As Int, Value As Object)
   Dim PersonaAssociataAllItem As tPersona = Value
   Log(PersonaAssociataAllItem.Nome)
   Log(PersonaAssociataAllItem.Cognome)
   Log(PersonaAssociataAllItem.Eta)
 

Schakalaka

Active Member
Licensed User
Grazie!
sono riuscito a capire, ed applicare.
inoltre l' ho implementato con il lazy loading..

Sono anche passato da mysql, al locale sqlite. il risparmio di codice è notevole.


Ma non è finita qui.
Giusto per complicarmi un po, vorrei aggiungere lo Swipe, tipo per modificare uno dei valori o eliminare il record

Ho già aggiunto il codice necessario, preso dall' esempio,
... "ma dove me lo attacco"?


B4X:
Sub DlMovimenti
.....
    CvlMovTot.Clear

    
    If result.RowCount > 0 Then
        Do While result.NextRow
            Dim CardItem As dtransazione
            CardItem.txtData = result.GetString("movData")
            CardItem.txtconto = result.GetString("movConto")
            CardItem.txtcategoria = result.GetString("movCategoria")
            CardItem.txtDescrizione = result.GetString("movDescrizione")
            CardItem.txtbeneficiario = result.GetString("movPersona")
            CardItem.txtprice = result.GetString("movImporto")
            
    Dim dataString As String = CardItem.txtData ' Sostituisci con la tua data

            ' Verifica che la lunghezza della stringa sia almeno 10 (per evitare errori)
            If dataString.Length >= 10 Then
                ' Estrai le ultime 4 cifre
                Dim ultime4Cifre As String = dataString.SubString(dataString.Length - 4)
            Else
                Log("La stringa della data non è nel formato corretto.")
            End If
    
            If CardItem.txtprice > 0 Then
                img = "increaseappicon.png"
            Else
                img = "moneydownicon.png"
            End If
            
            CardItem.imgg = img
            Dim p As B4XView  = xui.CreatePanel("")
            p.SetLayoutAnimated(0, 0, 0, CvlMovTot.AsView.Width, 145dip)
            CvlMovTot.Add(p,CardItem) 
           

        Loop

questo sarebbe il codice per aggiungere la funzionalità:
B4X:
            Swipe.CreateItemValue("", Array("Action 1", "Action 2", "Action 3"))

B4X:
Private Sub CvlMovTot_VisibleRangeChanged (FirstIndex As Int, LastIndex As Int)

    Dim ExtraSize As Int = 25 'List size
    For i = Max(0, FirstIndex - ExtraSize) To Min(LastIndex + ExtraSize, CvlMovTot.Size - 1)
        Dim Pnl As B4XView = CvlMovTot.GetPanel(i)
        If i > FirstIndex - ExtraSize And i < LastIndex + ExtraSize Then
            If Pnl.NumberOfViews = 0 Then 'Add each item/layout to the list/main layout
                Dim tdettagli As dtransazione = CvlMovTot.GetValue(i)
                Pnl.LoadLayout("clvMovTot")
                lblName.Text = tdettagli.txtDescrizione
                lblImporto.Text = tdettagli.txtprice & " €"
                lblData.Text = tdettagli.txtData
                lblTipo.Text = tdettagli.txtcategoria
                lblconto.Text = tdettagli.txtconto
                lblPerson.Text = tdettagli.txtbeneficiario
                AjustaImageView(imgMov,tdettagli.imgg)
                
                If tdettagli.txtcategoria <> "Generale" Then
                    lblPerson.Visible = True
        
                Else
                    lblPerson.Visible = False
                    lblImporto.Left = 40%x
                End If
                
            End If
        Else 'Not visible
            If Pnl.NumberOfViews > 0 Then
                Pnl.RemoveAllViews 'Remove none visable item/layouts from the list/main layout
            End If
        End If
    Next
End Sub
 
Salve, ho scaricato il programma, sono all'inizio della programmazione. Se lo avvio mi esce sull'emulatore di Android Studio. Se premo su Apri designer si apre la finestra vuota del designer, come si fa a visualizzare la custom view delle due pagine? Sto creando un programma per comandare Arduino, ho una pagina principale con i vari menù, cliccando su un bottone si deve aprire la relativa pagina per modificare dei parametri e poi ritornare alla pagina principale. Qual'è il sistema per fare ciò? In effetti è quello che accade in questo programma cliccando sul bottone Aggiungi cose.
 

Sagenut

Expert
Licensed User
Longtime User
Salve, ho scaricato il programma, sono all'inizio della programmazione. Se lo avvio mi esce sull'emulatore di Android Studio. Se premo su Apri designer si apre la finestra vuota del designer, come si fa a visualizzare la custom view delle due pagine? Sto creando un programma per comandare Arduino, ho una pagina principale con i vari menù, cliccando su un bottone si deve aprire la relativa pagina per modificare dei parametri e poi ritornare alla pagina principale. Qual'è il sistema per fare ciò? In effetti è quello che accade in questo programma cliccando sul bottone Aggiungi cose.
E' meglio se apri una tua discussione con la tua richiesta magari allegando il tuo inizio di progetto.
 
Top