Drei Fragen zu GUI, Datumsabfrage und E-Mails

  • Antworten:9
Yorrick R.
  • Forum-Beiträge: 60

02.02.2012, 21:12:25 via Website

Hallo Leute, ich habe eine handvoll Fragen an euch:

1. In meiner App aktualisiere ich Daten über das Internet und ich hätte gerne, dass während die Methode ausgeführt wird, eine ProgressBar eingeblendet wird (egal ob Kreis oder Leiste, wobei mir diese in Kombination mit einem TextView am liebsten wäre). Ich versuche das indem ich während dessen in einem Frame eine ProgressBar initiiere und darunter in einem TextView den Text von " " auf "laden..." nach "fertig" ändere. Also:

Methode beginnt
-> ProgressBar wird erzeugt
-> TextView auf "laden..." gesetzt
-> Methodenzeugs wird gemacht
->ProgressBar wird entfernt
->TextView auf "fertig" gesetzt

Doch bisher friert die App während der Methode einfach nur ein und am Ende wird die GUI verändert. Also, man sieht dann nur "fertig".
Wie schaffe ich es, dass die GUI-Elemente "live" angezeigt werden und die GUI am besten nicht einfriert?

2. Ich würde gerne eine zeitlich begrenzte Beta an ein paar Freunde geben und habe versucht mithilfe von GregorianCalendar eine Überprüfung des Datums einzubauen. Ich habe die API so verstanden, dass wenn ich ein GregorianCalendar()-Objekt ohne Parameter startet, das aktuelle Datum übernommen wird. Ich versuche nun zwei GC-Objekte mit .equal() zu vergleichen, dies klappt aber nur, wenn ich beiden Parameter mitgegeben habe. Jemand eine Idee wie das klappt?

3. Ich würde gerne bei einem Klick auf ein ListActivity-Element ein ein E-Mailprogramm mit einer aus einer SQLite-Tabelle erhaltenen E-Mailadresse öffnen. Ich fand dann ein paar Beispiele die alle sehr ähnlich waren nur leider bekomme ich es nicht hin, dass die Adresse mit übergeben wird. Weiß jemand Rat?
Der Code:
1@Override
2 public void onListItemClick(ListView parent, View view, int position, long id){
3 Log.i(TAG, "onListItemClick");
4 /*String mail = lcursor.getString(4);
5 Log.i(TAG, mail);
6 Intent intent = new Intent(Intent.EXTRA_EMAIL);*/
7
8 Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
9
10 String[] recipients = new String[]{lcursor.getString(4)}; //original: String[] recipients = new String[]{"my@email.com", "",};
11 Log.i(TAG, lcursor.getString(4)); //Bekomme hier die gewünschte EMail korrekt angezeigt.
12
13 emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, recipients);
14
15 emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Test");
16
17 emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "This is email's message");
18
19 emailIntent.setType("text/plain");
20
21 startActivity(Intent.createChooser(emailIntent, "Send mail..."));
22 }

Ich benutze momentan der Emulator und baue auf Android 2.2 auf.
Ach und wenn ich schon dabei bin: welches Layout eignet sich am besten wenn man in ListActivity-Einträgen mehrere TextViews(/andere GUI-Objekte) in einer Zeile, nebeneinander darstellen will? :(

Antworten
Stefan S.
  • Forum-Beiträge: 560

03.02.2012, 07:04:21 via Website

Das mit der Progressbar ist nicht so eine Sache. Es gibt verschiedene Möglichkeiten dies zu erzeugen.
Ich selber benutze meistens ein Runnable oder AsyncTask. Versuch dich mal über diese zwei Dinger schlau zu machen.

Zum Layout:
Wenn alles schön nebeneinander stehen soll ginge natürlich ein LinearLayout. Was auch super funktioniert wäre ein RelativeLayout.

Antworten
Felix
  • Forum-Beiträge: 259

03.02.2012, 16:13:06 via Website

Tach!

Yorrick R.
Doch bisher friert die App während der Methode einfach nur ein und am Ende wird die GUI verändert. Also, man sieht dann nur "fertig". Wie schaffe ich es, dass die GUI-Elemente "live" angezeigt werden und die GUI am besten nicht einfriert?

Das ist eine der gravierenden Designentscheidungen von Android (manche sagen Fehler dazu). Das UI läuft nicht separiert. Wenn du was langwieriges machst, wird es nicht aktualisiert. Langlaufende Dinge sollten deshalb in einem anderen Thread laufen. AsyncTask wurde ja schon genannt.

Ich versuche nun zwei GC-Objekte mit .equal() zu vergleichen, dies klappt aber nur, wenn ich beiden Parameter mitgegeben habe.

Wenn du dir den Quellcode der Klasse anschaust, wirst du feststellen, dass beim parameterlosen Aufruf des Konstruktors letztlich die aktuelle Zeit in Millisekunden gesetzt wird. Vermutlich ist dein System nicht schnell genug, zweimal dieselbe Millisekunde zu treffen. Wenn du die Zeit nicht brauchst, kannst du sie definiert auf 0-Werte setzen.

Ich würde gerne bei einem Klick auf ein ListActivity-Element ein ein E-Mailprogramm mit einer aus einer SQLite-Tabelle erhaltenen E-Mailadresse öffnen. Ich fand dann ein paar Beispiele die alle sehr ähnlich waren nur leider bekomme ich es nicht hin, dass die Adresse mit übergeben wird. Weiß jemand Rat?

Der erste Rat ist, genauer zu beschreiben, woran es hapert. Der zweite ist, dass jede View eine Eigenschaft namens Tag hat, der man Werte mitgeben kann, die man dieser View zuordnen möchte. Die Elemente der ListView könnten die Email-Adresse im Tag mit sich führen, die du dir dann beim onListItemClick-Ereignis holen kannst.

Ach und wenn ich schon dabei bin: welches Layout eignet sich am besten wenn man in ListActivity-Einträgen mehrere TextViews(/andere GUI-Objekte) in einer Zeile, nebeneinander darstellen will?

Siehe Android-Dokumentation, Hello-Views-Tutorials. Da lernt man als erstes das LinearLayout kennen. Es kann auch sein, dass für deinen Fall eher ein TableLayout statt einer ListView infrage kommt, speziell dann, wenn du gleichgroße Spalten benötigst.


Felix.

Antworten
Yorrick R.
  • Forum-Beiträge: 60

03.02.2012, 18:11:08 via Website

Das ist eine der gravierenden Designentscheidungen von Android (manche sagen Fehler dazu). Das UI läuft nicht separiert. Wenn du was langwieriges machst, wird es nicht aktualisiert. Langlaufende Dinge sollten deshalb in einem anderen Thread laufen. AsyncTask wurde ja schon genannt.

Danke, an euch beide, dass mit dem AsyncTask kannte ich noch nicht. Und ob diese Designentscheidung gut oder schlecht ist, kann ich als Laie auch nicht beurteilen bis darauf, dass es so ersteinmal etwas umständlich erscheint.

Es kann auch sein, dass für deinen Fall eher ein TableLayout statt einer ListView infrage kommt, speziell dann, wenn du gleichgroße Spalten benötigst.

Das nebeneinander Stellen von GUI-Elementen, habe ich mit RelativeLayout so wie ich mir es vorgestellt habe hin bekommen, wobei TableLayout auch eine gute Idee ist. LinearLayout bekam ich selbst mit der Eclipse-GUI nicht so hin, macht aber jetzt auch nichts mehr.

Der erste Rat ist, genauer zu beschreiben, woran es hapert.

Mein Problem war, dass die gewünschte E-Mail-Adresse nicht mitübergeben worden ist. Dies lag wohl daran, dass ich bei der erzeugung des Arrays erst cursor.getString(4); ausgeführt habe. Ich habe jetzt erst einen String erzeugt und die Adresse dorthin übergeben und dann diesen in den Array eingefügt. Selbst wenn es nicht daran gelegen haben sollte, jetzt klappt es.

Wenn du die Zeit nicht brauchst, kannst du sie definiert auf 0-Werte setzen.

Ich habe leider gerade nicht meinen Rechner mit Eclipse vor mir, konnte aber schon zumindest nochmal in der Android API und in Google suchen.
Leider war der einzige Konstruktor der einigermaßen ähnlich ist dieser hier:
GregorianCalendar(int year, int month, int date, int hour, int minute, int second)
Constructs a GregorianCalendar with the given date and time set for the default time zone with the default locale.
Der Punkt ist, ich verstehe schlicht und ergreifend nicht, wie ich das Objekt richtig initiiere, sodass ich das aktuelle Datum mit einem vordefinierten Datum (ohne explizite Uhrzeit, wenn man nur Datum angibt, wird die Uhr wohl automatisch auf Mitternacht "gestellt") vergleichen kann.

— geändert am 03.02.2012, 18:11:51

Antworten
Felix
  • Forum-Beiträge: 259

03.02.2012, 22:56:03 via Website

Tach!

Und ob diese Designentscheidung gut oder schlecht ist, kann ich als Laie auch nicht beurteilen bis darauf, dass es so ersteinmal etwas umständlich erscheint.

Ja, für dich als Programmierer ist es etwas umständlicher, weil du zwei Threads hast und die Kommunikation zwischen zwei Threads besondere Anforderungen stellt. Der Anwender hingegen möchte gern ein flüssiges Bedienerlebnis und kein Geruckel oder erst dann Reaktionen sehen, wenn das Programm grad mal Luft hat. Deshalb sind (so las ich) in den beiden anderen Systemen UI und Anwendungslogik von vorn herein getrennt. (Und der UI-Thread müsste dann auch mit höchster oder sehr hoher Priorität laufen.)

Der Punkt ist, ich verstehe schlicht und ergreifend nicht, wie ich das Objekt richtig initiiere, sodass ich das aktuelle Datum mit einem vordefinierten Datum (ohne explizite Uhrzeit, wenn man nur Datum angibt, wird die Uhr wohl automatisch auf Mitternacht "gestellt") vergleichen kann.

Dafür gibt es zwei Wege. Du nimmst den Konstruktor, der Jahr, Monat und Tag entgegennimmt sowie die Zeit von selbst auf 0 setzt und übergibst ihm diese drei Werte, die du anderswo herbekommst. Oder du nimmst den parameterlosen Konstruktor und setzt anschließend die vier Zeit-Werte (Stunde, Minute, Sekunden, Millisekunden) auf 0.


Felix.

Antworten
Yorrick R.
  • Forum-Beiträge: 60

05.02.2012, 19:01:25 via Website

Also, inzwischen klappt alles, nur das mit dem Datum will nicht:

1public class Hauptmenue extends Activity {
2 /** Called when the activity is first created. */
3
4 public GregorianCalendar d1 = new GregorianCalendar(); //Aktuelles Datum
5 public GregorianCalendar d2 = new GregorianCalendar(2012, 2, 5);
6
7 private static final String TAG = Hauptmenue.class.getSimpleName();
8
9 @Override
10 public void onCreate(Bundle savedInstanceState) {
11 super.onCreate(savedInstanceState);
12
13 d1.set(GregorianCalendar.HOUR_OF_DAY, 1);
14 d1.set(GregorianCalendar.MINUTE, 0);
15 d1.set(GregorianCalendar.SECOND,0);
16 d1.set(GregorianCalendar.MILLISECOND,0);
17
18 d2.set(GregorianCalendar.HOUR_OF_DAY,1);
19 d2.set(GregorianCalendar.MINUTE, 0);
20 d2.set(GregorianCalendar.SECOND,0);
21 d2.set(GregorianCalendar.MILLISECOND,0);
22
23
24 boolean k = d1.equals(d2);
25 if (k == true){
26 setContentView(R.layout.main);
27 Log.e(TAG, "wahr");
28 } else{
29 setContentView(R.layout.main2);
30 Log.e(TAG, "falsch");
31 }
32
33 Log.i(TAG, "Hauptmenue gestartet.");
34
35
36 }

Ich habe schon verschiedene Vorgehensweisen und Beispiele ausprobiert aber ich bekomme es einfach nicht hin. Sieht jemand den Fehler?

Antworten
Felix
  • Forum-Beiträge: 259

05.02.2012, 19:23:04 via Website

Tach!

Nimm compareTo(). equals() vergleicht Objektreferenzen und keine Inhalte.


Felix.

Antworten
Yorrick R.
  • Forum-Beiträge: 60

05.02.2012, 20:31:10 via Website

Hmmm, also, wenn ich den code so ändere, kommt immer "wahr" heraus.8o

24 int k = d1.compareTo(d2);
25 if (k == -1){
26 setContentView(R.layout.main);
27 Log.e(TAG, "wahr");
28 } else{
29 setContentView(R.layout.main2);
30 Log.e(TAG, "falsch");
31 }

Nur um es nochmal genau zu sagen was ich vorhabe, ich will überprüfen ob das aktuelle Datum (d1) noch kleiner ist als das vorgegebene Datum (d2)...

Antworten
Felix
  • Forum-Beiträge: 259

05.02.2012, 21:55:49 via Website

Tach!

Hmmm, also, wenn ich den code so ändere, kommt immer "wahr" heraus.

Was völlig korrekt ist im Sinne dieser äußerst intelligenten Java-Eigenart, die Monate von 0 bis 11 zu nummerieren.


Felix.

Antworten
Yorrick R.
  • Forum-Beiträge: 60

06.02.2012, 00:26:13 via Website

Danke! Darauf wäre ich niemals gekommen.

Antworten