JavascriptProva

domenica 17 gennaio 2016

Ottenere il popolamento della lista di suggerimenti di una AutoCompleteTextView direttamente da un database

setFilterQueryProvider.
dovrebbe eseguire la query con le limitazioni date da constraint.
Restituisce getCursor(constraint).
Il problema è che getCursor non ce l'abbiamo.
E' una funzione che deve essere creata, ed è qui che non ci capisco niente.

Ogni volta che cambia il contenuto della textview scatta un metodo che mi mostra la stringa constraint.
Cerchiamo di riprodurla.

Non mi è chiaro se la view che è stata inflatata nel metodo newView deve essere... Se è una TextView, non si fa come si è fatto nell'inflatare una view esterna, ossia cercare dentro di essa una TextView, ma se ne imposta direttamente il testo prendendo il valore da una colonna del Cursor.

 class Adapter extends CursorAdapter{

  public Adapter(Context context, Cursor c) {
   super(context, c);
   
  }

  @Override
  public View newView(Context context, Cursor cursor, ViewGroup parent) {
   LayoutInflater inflater=(LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
   TextView v=(TextView)inflater.inflate(android.R.layout.simple_dropdown_item_1line,null);
   return v;
  }

  @Override
  public void bindView(View view, Context context, Cursor cursor) {
   ((TextView)view).setText(cursor.getString(0));
   
  }
  
 }
Ecco: così, nel momento in cui viene digitato un testo nella autoComplete, la lista viene popolata di TUTTI i valori presenti nella colonna 0 del Cursor.
Invece dobbiamo fare in modo che venga popolata soltanto di quelli che iniziano con i caratteri digitati. E' quello il problema!

E abbiamo conseguito una prima acquisizione.

Ora, c'è un evento che si verifica a ogni digitazione di testo nella autoComplete.
Cerco di ricordarlo e di catturarlo.
  @Override
  public Cursor runQueryOnBackgroundThread(CharSequence constraint){
   Log.d("CONSTRAINT",""+constraint);
   return null;
   
  }
01-17 15:21:07.555: D/CONSTRAINT(2233): null
01-17 15:21:08.945: D/CONSTRAINT(2233): ci
01-17 15:21:10.225: D/CONSTRAINT(2233): cia
01-17 15:21:11.756: D/CONSTRAINT(2233): ciao
Ecco: quando la lunghezza della stringa è di due o più caratteri, questa funzione viene eseguita e su LogCat mi appaiono i caratteri digitati.
Ora devo praticamente elaborare qualcosa che da un Cursor, ossia da una serie di records, riconosca l'inizio della stringa e mi scriva i valori che iniziano con quell'inizio.

E finalmente ci sono riuscito!!!

Ho modificato la query in questo senso (codice dell'helper):
  public Cursor query(String args){
   SQLiteDatabase db=this.getWritableDatabase();
   Cursor crs=db.rawQuery("select categoria as _id from TabCat where categoria like '%"+args+"%' ", null);
   crs.moveToFirst();
   return crs;
  }
e poi ho aggiunto, nel codice del CursorAdapter:
  @Override
  public Cursor runQueryOnBackgroundThread(CharSequence constraint){
   Log.d("CONSTRAINT",""+constraint);
   if(constraint==null){
    return helper.query(" ");
   } else{
    return helper.query(""+constraint);
   } 
  }
Ecco, adesso ottengo una lista adeguata per la mia AutoCompleteTextView!
Codice completo con classe che estende SQLiteOpenHelper per la creazione del database e classe che estende CursorAdapter:
public class MainActivity extends Activity {
 
 Helper helper;
 private AutoCompleteTextView autoComplete;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  setContentView(R.layout.activity_main);
  
  autoComplete=(AutoCompleteTextView)findViewById(R.id.autoCompleteTextView1);
  helper=new Helper(this);
  helper.save("foto");
  helper.save("cartoni");
  helper.save("mostri");
  
  
  Adapter adapter=new Adapter(this,helper.query(""));
   
 
  
  autoComplete.setAdapter(adapter);
 }
 
 class Adapter extends CursorAdapter{

  public Adapter(Context context, Cursor c) {
   super(context, c);
   
  }

  @Override
  public View newView(Context context, Cursor cursor, ViewGroup parent) {
   LayoutInflater inflater=(LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
   TextView v=(TextView)inflater.inflate(android.R.layout.simple_dropdown_item_1line,null);
   return v;
  }

  @Override
  public void bindView(View view, Context context, Cursor cursor) {
   ((TextView)view).setText(cursor.getString(0));
   
  }
  
  @Override
  public Cursor runQueryOnBackgroundThread(CharSequence constraint){
   if(constraint==null){
    return helper.query(" ");
   } else{
    return helper.query(""+constraint);
   } 
  }

  
 }
 
 class Helper extends SQLiteOpenHelper{

  public Helper(Context context) {
   super(context, "mioDatabase", null, 1);
   
  }

  @Override
  public void onCreate(SQLiteDatabase db) {
   db.execSQL("create table TabCat(categoria text unique, path text )");
   
  }
  
  public void save(String categoria){
   SQLiteDatabase db=this.getWritableDatabase();
   ContentValues values=new ContentValues();
   values.put("categoria", categoria);
   values.put("path", "path");
   db.insert("TabCat", null, values);
  }
  
  public Cursor query(String args){
   SQLiteDatabase db=this.getWritableDatabase();
   Cursor crs=db.rawQuery("select categoria as _id from TabCat where categoria like '%"+args+"%' ", null);
   crs.moveToFirst();
   return crs;
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
   // TODO Auto-generated method stub
   
  }
  
  
 }
C'è un problema.
Come faccio a ottenere nella autoComplete il testo?
Il metodo runQueryOnBackgroundThread mi restituisce un cursor.
I suggerimenti mi risultano congruenti.
Ma poi, quando vado a cliccare sul suggerimento, ottengo una strana formula nella autoComplete al posto della stringa presente come suggerimento.
Perché?

Probabilmente perché, per qualche motivo che non riesco ancora a mettere a fuoco, viene scelta un'altra colonna del cursore per riempire la TextView una volta che sia stata selezionata la voce.
Con un po' di intuito, seguendo questo link, ho sistemato le cose aggiungendo al CursorAdapter questa funzione:
  @Override
  public String convertToString(Cursor cursor) { 
   return cursor.getString(0); 
  } 
e tutto sembra risolto!

Nessun commento:

Posta un commento