Ich habe ein OnFocusChangeListener auf die EditTexte gelegt; funktioniert 1a.
Beiträge von Tion
-
-
Tut mir leid, ich verstehe das nicht so ganz...
Bedeutet das jetzt, dass er im "Sekundentakt" das getView ausführt und quasi immer "neue" EditTexts rendert, wenn die sichtbar sind ? Ich setze den Adapter nur 1 mal, und meines wissens nach ändert sich der ListView ja nicht, bis der Adapter erneut gesetzt wird, oder ? In der Doc konnte ich sowohl unter ListView als auch unter ListAdapter nichts dazu finden...Gewollt ist, dass ich 20 Boxen in dem ListView habe, in die dann 20 andere Felder drinne sind. Das funktioniert auch alles. Nur kann ich die Felder nicht bearbeiten. Bei der Anforderung der Box "mache ich sie fertig", indem ich 20 Felder inflate, die in die Box setze und die Box dann an den ListView zurückgebe.
Edit: Nach einer tiefgreifenden Suche bei Google habe ich die Lösung gefunden; für alle anderen suchenden:
Wie killphil75 gesagt hat, muss man den Inhalt des EditTextes speichern. Da kommt noch allerdings das Problem, dass der EditText ständig den Focus verliert oder der Cursour "wild" rumspringt; dazu in der Manifest einfach folgenden Wert in der Activity setzen:Code<activity android:name="main.activity" android:label="@string/activity_title" android:windowSoftInputMode="adjustPan" > <!-- den hier setzen --> </activity>
. Ob es was zur Lösung beiträgt, weiß ich nicht, in dem Code wurde auch
gesetzt; ich gehe also mal davon aus.
Danke für den Anstoß, ich war schon dabei, mich bereit zu machen, alles auf einen ScrollView mit einem ListView, in den ich alles reinstecke, umzuschreiben, wobei das wohl nicht so ein Aufwand währe.
Quelle 1 | Quelle 2 ( wird auch in Quelle 1 verlinkt )
Edit 2: Quellen etwas kleiner
-
Heyho, ich nochmal;
Nachdem ich ja letztes mal schon angefragt habe, das Problem weiterhin bestand und sich als ein anderes ausgab, frage ich noch mal; dieses mal besser vorbereitet und aufbereitet.
Ich habe das ganze in ein neues Projekt exportiert - der Bug besteht auch hier, Android 2.3.7 -> https://dl.dropbox.com/u/58558990/src-2.zip
Und wer nichts downloaden möchte, dem habe ich den Code hier noch mal hingepackt:
Java
Alles anzeigenpackage de.tionsys.test; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((ListView)findViewById(R.id.profile_list)).setAdapter(new BaseAdapter() { @Override public View getView(int position, View convertView, ViewGroup parent) { convertView = getLayoutInflater().inflate(R.layout.profile_box, null); for(int i = 0; i < 20; i++) { View v = getLayoutInflater().inflate(R.layout.profile_item, null); ((TextView)v.findViewById(R.id.profile_item_key)).setText("123"); ((EditText)v.findViewById(R.id.profile_item_value)).setText("345"); ((LinearLayout)convertView).addView(v); } return convertView; } @Override public long getItemId(int position) { return 0; } @Override public Object getItem(int position) { return null; } @Override public int getCount() { return 20; } }); } }
Problem: Man kann keinen einzigen EditText bearbeiten; man kann sie anklicken und tippen, aber die Buchstaben erscheinen nicht. Und wenn man es mit buggen geschafft hat ( viele Tasten schnell drücken ) und dem EditText wieder den Focus nimmt, verschwindet der Text wieder.
Meine Frage jetzt: Jemand eine Ahnung woran das liegt ?Android 2.3.7, Gerootet, App läuft ohne Root.
Erneut am verzweifeln,
Tion
-
Das habe ich gerade schon behoben; hing damit zusammen, dass ich alles golbalisiert hatte, und ich dachte schon, ich hätte den Bug damit weg, aber...
Ich bin jetzt so weit, dass es funktioniert, weil ich das "onResponse" einfach in keiner anderen Funktion drinne habe... Aber wenn ich es bei einem AsyncTask unter "onPostExecute" ausführe, geht es nicht; selbst wenn ich noch ein "runOnUIThread" dazwischen setze... Ich vermute, dass ich den ActivityContext o.ä. verliere, während ich die Schritte durchgehe, aber warum ?
Java
Alles anzeigenpublic class ProfileRequestTask extends AsyncTask<Package, String, String> { private Exception e = null; private ResponseListener listener; private Activity i; private ProgressDialog pd; public ProfileRequestTask(Activity a) { this.i = a; pd = new ProgressDialog(this.i); pd.setIndeterminate(true); pd.setTitle(this.i.getString(R.string.request_title)); pd.setMessage(this.i.getString(R.string.request_connect)); pd.show(); } public void setListener(ResponseListener l) { this.listener = l; } @Override protected String doInBackground(Package... packages) { String url = "[URL hier]"; HttpClient httpc = new DefaultHttpClient(); HttpGet req = new HttpGet(); req.setURI(new URI(url)); HttpResponse resp = httpc.execute(req); // Auslesen der Webseite HttpEntity entity = resp.getEntity(); InputStream content = entity.getContent(); StringBuilder builder = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(content)); String line; while ((line = reader.readLine()) != null) builder.append(line); return builder.toString(); } @Override public void onPostExecute(String ret) { pd.dismiss(); if(this.listener == null) return; if(this.e != null) { listener.onError(this.e); } else { listener.onResponse(ret); } } }
Das Response-Listener-Interface sieht so aus:
Javapackage de.tionsys.internet; public interface ResponseListener { public void onResponse(String response); public void onError(Exception error); }
Und der Zugriff auf den AsyncTask:
Java
Alles anzeigenProfileRequestTask frt = new ForegroundRequestTask(this); frt.setListener(new ResponseListener() { @Override public void onResponse(final String response) { requestResponse(response); } @Override public void onError(Exception error) { Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show(); } }); frt.execute(); // Die Funktion requestResponse ( steht natürlich nicht so in der onCreate ) public void requestResponse(String response) { runOnUiThread(new Runnable() { public void run() { try { onResponse(new JSONArray("[{\"box.name\":\"box.general\",\"var.age\":\"17\"},{\"box.name\":\"box.location\",\"var.city\":\"\",\"var.country\":\"\"},{\"box.name\":\"box.language\",\"var.lang\":\"\",\"var.lang_other\":\"\"}]")); } catch (JSONException e) { e.printStackTrace(); } } }); }
Was mich verwirrt, ist, dass alles geht, wenn ich das Activity.onResponse direkt in der onCreate-Methode aufrufe, wie ich es in dem Debug-Projekt oben getan habe - wenn ich es aber so mache, geht es nicht.
ProfileRequestTask sieht nicht exact so aus, sondern etwas anders; habe das ganze mal so kopiert, wie es ausgeführt werden würde. Dabei hat sich nur das "doInBackground" geändert.
Ich weiß leider nicht, was ich hier übersehe... Ich lasse den doch noch mal extra im UI-Thread laufen...
Edit: Ich habe jetzt noch ein bischen rumprobiert und bin dabei zu der Feststellung gekommen, dass, wenn ich anstelle des TextViews einen EditText nehme, dieser einen "Schreibschutz" hat - bedeutet, man kann den Inhalt nicht ändern.
Finde es etwas blöd, wenn wir uns jetzt hier von dem eigentlichen Thema so weit "distanzieren", markiere das deswegen als "erledigt", teste noch ein bischen rum und frage zur Not in einem neuen Thread zum passendem Thema nach.
Danke an alle, die versucht haben zu helfen -
Das klingt ausgesprochen verwunderlich.
Dir stürzt dabei auch nix ab oder so?
Bau doch bitte mal ein kleines Testprojekt, dass nur aus den nicht funktionierenden Teilen besteht und lad das hier hoch.
Dann schau ich mir gern mal das Gesamtkonstrukt an.Das ist ja witzig; in dem Testprojekt geht alles ?
Ich lade das trotzdem mal hoch, damit der Zusamenhang klar wird - https://dl.dropbox.com/u/58558990/src.zipDas ist in etwa die App, nur, dass ich in den Layouts den Kopfbereich auskommentiert habe ( weil der wieder aus 3 Layouts besteht und von einer eigenen Klasse behandelt wird, [...] ) und der Zugriff auf den Webserver wegfällt.
Werde jetzt mal hier und da ein paar Sachen bei meiner App wegstreichen und testen, ob das geht.
schymura: Das mit der extra Methode hat auch nicht geklappt; und globale Variablen kann ich wohl nicht nehmen, da ich beim Programmieren nicht weiß, um wie viele TextView's es sich handelt, und ich diese später dann auch wieder auslesen muss und an den Server "zurückfunken" muss...
Sonst zur Not könnte ich trotzdem auch noch eine Variable "zwischenklemmen", allerdings hilft mir das nicht weiter, wenn der benutzer nicht sieht, dass das Feld auch wirklich bearbeitet wurde... -
Habe das jetzt mal so gemacht:
Java
Alles anzeigen// Dialoge public TextView active_value; public AlertDialog.Builder active_builder; public EditText active_et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_change_profile); active_builder = new AlertDialog.Builder(this); active_builder.setTitle("init"); active_et = new EditText(this); active_builder.setView(active_et); }
Dann wieder das Erstellen des OnClickListeners, hat sich nichts dran geändert
Java
Alles anzeigenfinal View v = getLayoutInflater().inflate(R.layout.profile_item, null); TextView keyview = ((TextView)v.findViewById(R.id.profile_item_key)); TextView valueview = ((TextView)v.findViewById(R.id.profile_item_value)); keyview.setText(ProfileFieldTranslator.translate(key, getApplicationContext())); try { valueview.setText(obj.getString(key)); } catch (JSONException e) { } // Der Wert lässt sich per Klick ändern valueview.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v2) { changeText(ProfileFieldTranslator.translate(key, getApplicationContext()), (TextView)v2); } });{/java] Und der Dialog [code=java] // Dialog anzeigen: Text public void changeText(String title, TextView tv) { this.active_value = tv; active_builder.setTitle(title); active_et.setText(active_value.getText()); active_builder.setPositiveButton(getString(R.string.profile_edit_save), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { active_value.setText(active_et.getText().toString()); } }); active_builder.setNegativeButton(getString(R.string.profile_edit_cancel), null); active_builder.create().show(); }
Das, was mich daran am meisten verwirrt, ist ja, dass ich den Inhalt vom EditText ausgeben kann ( und der wird richtig ausgegeben ) und ich kann den Inhalt vom TextView mit "statischen" Texten ( also keine Variablen enthalten ) verändern. Selbst innerhalb der OnClick-Methode des AlertDialoges...
Eine Alternative, zu der ich jedoch ungerne greifen möchte, währe, anstelle des TextViews ein EditText direkt da rein zu "klatschen" - das sieht aber nicht schön aus, da ich nur weniger als die Hälfte des Bildschirmes ( Portrait mode ) habe.
-
Das ist von der Theorie her eine geniale Idee, das zu debuggen, werde ich mir merken.
Java
Alles anzeigen[...] // Den Inhalt von dem TextView ( aktuell ) in den EditText schreiben // Write Content from TextView in EditText final EditText et = new EditText(this); et.setFilters(new InputFilter[]{ new TextFilter() }); et.setText(tv.getText()); et.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { Log.d("otChanged", s.toString()); } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d("otBeforeChanged", s.toString()); } @Override public void afterTextChanged(Editable s) { Log.d("otAfterChanged", s.toString()); } }); b.setView(et); [...]
Ausgabe:
Code04-09 01:17:14.959: D/otChanged(32046): T 04-09 01:17:14.959: D/otAfterChanged(32046): T 04-09 01:17:20.939: D/otBeforeChanged(32046): T 04-09 01:17:20.939: D/otChanged(32046): Te 04-09 01:17:20.939: D/otAfterChanged(32046): Te 04-09 01:17:23.469: D/otBeforeChanged(32046): Te 04-09 01:17:23.469: D/otChanged(32046): Tex 04-09 01:17:23.469: D/otAfterChanged(32046): Tex
Also kommt der eingegebene Text ( in diesem Fall "Tex" ) 100%ig auch an den EditText an; aber er kann trotzdem nicht in den TextView geschrieben werden...
Ich kann ja noch mal alles posten, was mir gerade aus LogCat unter die Finger kommt; Log-Level ist "debug"
Code
Alles anzeigen// Tippen auf den TextView 04-09 01:23:44.809: D/InputQueue(32046): Registering input channel '40911ee8 (client)' 04-09 01:23:47.259: D/InputQueue(32046): Registering input channel '40952f08 PopupWindow:40694d60 (client)' 04-09 01:23:47.469: W/Resources(32046): Converting to string: TypedValue{t=0x12/d=0x0 a=2 r=0x7f050086} [10x] 04-09 01:23:51.369: D/InputQueue(32046): Unregistering input channel '40952f08 PopupWindow:40694d60 (client)' // Tippen von "text" 04-09 01:24:46.359: D/otChanged(32046): T 04-09 01:24:46.359: D/otAfterChanged(32046): T 04-09 01:24:46.439: W/Resources(32046): Converting to string: TypedValue{t=0x12/d=0x0 a=2 r=0x7f050086} [10x] 04-09 01:24:46.749: D/otBeforeChanged(32046): T 04-09 01:24:46.749: D/otChanged(32046): Te 04-09 01:24:46.749: D/otAfterChanged(32046): Te 04-09 01:24:47.149: D/otBeforeChanged(32046): Te 04-09 01:24:47.149: D/otChanged(32046): Tex 04-09 01:24:47.149: D/otAfterChanged(32046): Tex 04-09 01:24:47.499: D/otBeforeChanged(32046): Tex 04-09 01:24:47.499: D/otChanged(32046): Text 04-09 01:24:47.499: D/otAfterChanged(32046): Text // Klicken auf Speichern 04-09 01:25:05.559: D/InputQueue(32046): Unregistering input channel '40911ee8 (client)' 04-09 01:25:05.769: W/Resources(32046): Converting to string: TypedValue{t=0x12/d=0x0 a=2 r=0x7f050086} [16x]
Habe ich noch nicht gepostet, fällt mir auf;
Getestet wird über USB auf meinem Motorola Motoluxe ( XT-615 ) und Android 2.3.7
IDE ist Eclipse, Handy ist gerootet, App läuft aber nicht als Root. -
Heyho ihr,
ich muss ja leider beichten, dass mich ein Problem zu eucht geführt hat; ich habe es vorher schon bei der entsprechenden Google-Gruppe versucht, aber die Herren brauchen länger als 24 Stunden, um mein Thema freizuschalten, was mir in die für mich gelegte Deadline ( der 31.04. ) überhaubt nicht passt
Mein Problem ist, dass ich den Inhalt von einem EditText in ein TextView schreiben muss; klingt recht einfach, funktioniert nur nicht so, wie es soll. Das Konzept ist in etwa so:
- Der Benutzer hat einen TextView
- Nach dem Klick darauf, öffnet sich ein AlertDialog mit einem EditText
- Wenn der Benutzer den AlertDialog absendet, wird der Inhalt des EditText's in in den TextView gschrieben.
Es funktioniert auch alles so weit, ich kann nach dem Absenden des AlertDialoges alles in den TextView schreiben, nur nicht dass, was im EditText steht.
Ein bischen Code...
Java
Alles anzeigenfinal View v = getLayoutInflater().inflate(R.layout.profile_item, null); ((TextView)v.findViewById(R.id.profile_item_key)).setText(ProfileFieldTranslator.translate(key, getApplicationContext())); try { ((TextView)v.findViewById(R.id.profile_item_value)).setText(obj.getString(key)); } catch (JSONException e) { } ((TextView)v.findViewById(R.id.profile_item_value)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v2) { changeText(ProfileFieldTranslator.translate(key, getApplicationContext()), (TextView)v.findViewById(R.id.profile_item_value)); } }); fields.add(new Connector(key, (TextView)v.findViewById(R.id.profile_item_key))); ((LinearLayout)convertView).addView(v);
Das ganze fügt das Layout profile_item ( bestehend aus 2 TextViews: profile_item_key und profile_item_value ) ein, setzt den Inhalt von Key und Value und legt einen OnClickListener auf das Value-Feld. Wird das geklickt, wrd folgende Code ausgeführt:
Java
Alles anzeigen// Dialog anzeigen: Text public void changeText(final String title, final TextView tv) { AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle(title); // Den Inhalt von dem TextView ( aktuell ) in den EditText schreiben // Write Content from TextView in EditText final EditText et = new EditText(this); et.setText(tv.getText()); b.setView(et); b.setPositiveButton(getString(R.string.profile_edit_save), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // DEBUG 1: Perhaps referrer to TextView has changed ( hasn't ) //Log.d("DBG", tv.toString()); //Log.d("DBG", et.toString()); // DEBUG 2: Write it in a variable and toast it, than write that variable in the TextView ( not working ) //final String str = (" "+ et.getText().toString() +" ").trim(); //Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show(); // tv.setText(str); // DEBUG 3: Starts like DEBUG2, but used the thread of UI explicit ( not working ) //runOnUiThread(new Runnable() { public void run() { tv.setText(str); } }); // DEBUG 4: Set content with no variable ( working ? :confused: ) // tv.setText("555"); // DEBUG 5: Write the content in a new String ( not working :confused: char[] buffer = new char[et.getText().length()]; et.getText().getChars(0, buffer.length, buffer, 0); tv.setText(new String(buffer)); } }); b.setNegativeButton(getString(R.string.profile_edit_cancel), null); b.create().show(); }
Wie man hier auch sieht, habe ich verschiedenes versucht, um das zu "fixxen".
Bei Versuch 1 habe ich erst einfach mal geguckt, ob der EditText ( Variable: et ) und der TextView ( Variable: tv ) existieren. Tun sie auch, sind beides gültige Resourcen.
Versuch 2 zeigt, wie ich versucht habe, einen neuen String zu erstellen, weil meine Vermutung dann dabei lag, dass vielleicht Pointer genutzt werden, der EditText am Ende der Funktion vielleicht vom Garbarage-Collector erwischt wird und dann weg ist.
Im Versuch 3 habe ich das Setzen explizit in den UI-Thread gesetzt, weil ich dann vermutete, dass der OnClickListener ( warum auch immer ) vielleicht in einem neuen Thread gepackt wird. Auch das hat nicht funktioniert.
Versuch 4 war denn ein Versuch, ob ich den richtigen TextView habe - habe ich, er hat erfolgreich "555" in den TextView geschrieben.
Letztenendes habe ich versucht, anders auf den Editable zuzugreifen, indem ich alles zuerst in einen Char-Array kopiert habe, und das dann in einen String gepackt habe; guess what, es ging nicht.
Ich kann den Inhalt auch nicht per tv.setText(et.getText().toString()) setzen, allerdings gibt Log.d("OUTPUT", et.getText().toString()) den Inhalt richtig aus.Ich habe echt keine Ahnung mehr, was ich versuchen könnte, und währe sehr erfreut, wenn jemand mir vielleicht auch nur eine Idee geben könnte;
Tion