TFT keyboard gives corrupted characters

hi im writing a keyboard program to let users enter data to another program, i have a keyboard setup (not finished) but when i write something the last letter always appears "corrupted" like a blue and red square, doesnt matter the length of the word being written, its always the last letter being strange.

im using a nodeMCU esp8266 and a ili9341 display

here is my code:

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <SPI.h>
#include <ArduinoJson.h>
#include <TFT_eSPI.h>
#include <WiFiClientSecureBearSSL.h>
TFT_eSPI tft = TFT_eSPI();
#include <XPT2046_Touchscreen.h>
#define TFT_NERO 0x0000
#define TFT_BIANCO 0xFFFF
XPT2046_Touchscreen ts(15);//15 pin gpio di CS
int coorCursX = 27;
int coorCursY = 37;
int posX = 20; //first key position
String Corrente = "";
const char* primaRiga[]// letters first line
        = { "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"};
        
const char* secondaRiga[]// letters second line
        = { "a", "s", "d", "f", "g", "h", "j", "k", "l",};

        
void tasto(int pos_tastX, int pos_tastY, String lettera){   //function creates the buttons, takes coordinates and prints a letter in the square
  tft.drawRect(pos_tastX, pos_tastY, 20, 20, TFT_BIANCO);
  tft.setCursor(pos_tastX+7, pos_tastY+7);// piu 7 pixel entrambe le direzioni rispetto a contorno tasto
  if (lettera == "ENT" or lettera == "DEL"){
    tft.setCursor(pos_tastX+1, pos_tastY+7);
  }
  tft.print(lettera);
   
}

void tastiera(){
  for (int i=0; i<10; i += 1){ //call the function "tasto" for every element in "primaRiga" so i creates a line with multiple buttons and the corresponding letters
    tasto(posX,150, primaRiga[i]);
    posX +=20;
  }
  posX = 20;
  for (int i=0; i<9; i += 1){ //makes the second line of keys
    tasto(posX,170, secondaRiga[i]);
    posX +=20;
  }
  
 tasto(220,150, "ENT"); //tasto speciale
 tasto(200,170, "DEL"); //tasto speciale
}

void cheTasto(int coordx, int coordy){ //checks if a button is pressed, if so adds the letters to a string, then prints the string
   //prende coordinate punto
   int xMap = map(coordx, 370 , 3880, 0, 320); //mappa coordinate strane display sui pixel effettivi
   int yMap = map(coordy, 250 , 3770, 0, 240);
   for (int i=0; i<10; i += 1){ //controlla se punto premuto e' tasto, se lo e' scrive lettera corrispondente
    
    if (xMap > posX && xMap < posX+20 && yMap > 150 && yMap < 170){ //se coordinate rientrano in quelle della prima casella
      Corrente += primaRiga[i]; 
      tft.fillRect(22,32,180,15, TFT_NERO );
      tft.setCursor(22,32);
      tft.print(Corrente);
      //Serial.print(primaRiga[i]);      //scrivi lettera corrispondente
      posX = 20; //resetta posizione di controllo
      coorCursX += 10;
      
      break;
    }
    else {
      posX+=20; //sposta la casella di controllo 20 pixel o una casella piu in la
      
      }
  }
  posX= 20;
  for (int i=0; i<9; i += 1){
    
    if (xMap > posX && xMap < posX+20 && yMap > 170 && yMap < 190){ //se coordinate rientrano in quelle della prima casella
      Corrente += secondaRiga[i]; 
      tft.fillRect(22,32,180,15, TFT_NERO );
      tft.setCursor(22,32);
      tft.print(Corrente);
      Serial.print(secondaRiga[i]); //scrivi lettera corrispondente
      posX = 20; //resetta posizione di controllo
      break;
    }
    else {
      posX+=20; //sposta la casella di controllo 20 pixel o una casella piu in la
      
      }
  }
  posX= 20;
  
  if (xMap > 200 && xMap < 220 && yMap > 170 && yMap < 190) { // if "DEL" key is pressed, removes the last element from the string being written
    Corrente = Corrente.substring(0, Corrente.length() - 1);
    tft.fillRect(22,32,180,15, TFT_NERO );
    tft.setCursor(22,32);
    tft.print(Corrente);
    
  }
}

void setup() {
  Serial.begin(115200);
  tft.init(); //inizializa display
  tft.fillScreen(TFT_BLACK);
  tft.setRotation(3); // horizontal display
  //codice da spostare in funzione tasto
  tastiera();
  ts.begin();// inizializza touch
  // ts.begin(SPI1); // use alternate SPI port
  ts.setRotation(1);
  while (!Serial && (millis() <= 1000));
  tft.drawRect(20, 30, 200, 20, TFT_BIANCO); //draws the rectangle in which you write
  tft.drawRect(220, 30, 1, 20, TFT_BIANCO);
}
  
 



void loop() {
  // put your main code here, to run repeatedly:
  
  if (ts.touched()){ //if display is touched call "cheTasto" to see which button has been pressed
    TS_Point p = ts.getPoint();
    cheTasto(p.x, p.y);
   
    int xMap = map(p.x, 370 , 3880, 0, 320);
    Serial.print(", x = ");
    Serial.print(xMap);
    int yMap = map(p.y, 250 , 3770, 0, 240);
    Serial.print(", y = ");
    Serial.print(yMap);
    delay(30);
    Serial.println();
    
  }
  delay(100);
}

What exactly do you mean by last letter? The last letter of a word after you hit enter or the last letter in a line?

What characters it does output? Does decide to: n̷͈̞͒ô̷̯ ̵̖̎͝t̶̡͍́h̸͔̅̀ả̴̼ṋ̷̛͝k̴̪̿͐ṡ̴̖̋͜ then this char: ṡ̴̖̋͜

the program appends the letter pressed to a string and then prints that string on screen, if i write "hello" the "o" gets corrupted

it gets corrupted like this, i wrote hello but it is sending me to hell so there is that, as you see the last letter appears strange, its always the last, no matter how long the word

i tried updating the screen very fast and the corruption still shows but only on the top row of pixels of the letter, if i stop updating it make its way down the letter like you see here