Listenelemente ansprechen in ListFragment

  • Antworten:17
  • Bentwortet
bazzey B.
  • Forum-Beiträge: 14

19.03.2014, 15:07:24 via Website

Hallo liebe Leute,

ich komme seit Tagen nicht mehr weiter, deshalb behellige ich euch mal in der Hoffnung ihr erlöst mich. Ich bin nicht so geübt im Beiträge schreiben, also wenn ich etwas vergessen habe zu erwähnen, schnell Bescheid sagen.

**Also mein Ziel ist folgendes:**

In meinem ListFragment habe ich in der Liste neben jedem Listeneintrag auch eine Checkbox, die ihren Status jeweils in einer Datenbank speichert. Hört sich ganz einfach an, aber ich bekomme es einfach nicht hin.

Ich beschränke mich im Folgenden auf das Fagment und lasse die Activity außen vor.

**Hier zunächst meine list_row.xml für die Listenzeilen**



**Nun die onListItemClick-Klasse in MeinListFragment.java**

Ich habe alles entfernt was meiner Meinung nach nicht mit dem Vorhaben zu tun hat. In der jetzigen Situation ist es so, dass bei Klick auf ein Listeneintrag eine neue Aktivity geöffnet wird und die ID der ausgewählten Reihe mit übergeben wird. Jetzt wäre es schön, das Abhaken Checkbox in der Datenbank zu speichern.



Ich stelle mir das ganz einfach vor. In der onListItemClick-Klasse wird doch das angeklickte Element identifiziert. Warum kann ich nicht für jedes Element in der list_row eine Methode erstellen?

Ich hoffe ich werde jetzt nicht fertig gemacht, weil die Frage zu banal ist oder so.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

19.03.2014, 15:21:08 via App

Habs noch net ganz verstanden.
Du hast ne ListView und ne checkbox.
Wenn du mitbekommen willst wann die cb gedrückt wird brauchst du dafür ne eigenen Listener. Und was genau soll passieren wenn ein List eintrag gedrückt wurde.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
impjor
  • Forum-Beiträge: 1.793

19.03.2014, 16:59:31 via Website

Bist du sicher, dass du das abhaken in einer Datenbank speichern möchtest? Wie soll das aussehen? Eine Art Log, dass um diese Uhrzeit jene Checkbox geklickt wurde? Oder willst du eine Datenbank, die für jede Checkbox einen Wert (gedrückt nicht gedrückt) speichern kann?
In jedem Fall wird das nicht so einfach gehen, da du bisher ja noch gar keine Datenbankanbindung hast. Am besten beschäftgist du dich erstmal mit SQLite, dann sollte das auch kein Problem sein.

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
bazzey B.
  • Forum-Beiträge: 14

19.03.2014, 17:30:35 via App

Doch, ich habe bereits eine SQLite Datenbankanbindung mit allem drum und dran. Klappt alles soweit. Der Status der Checkbox soll in der DB gespeichert werden. Beim Klick auf den Listeneintrag gibts ne Detailansicht dieses Eintrags.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

19.03.2014, 18:51:55 via App

Dann brauchst du auf der checkbox doch nur nen Changed listener.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
bazzey B.
  • Forum-Beiträge: 14

20.03.2014, 16:07:06 via Website

Vielen Dank für eure Versuche mir zu helfen. Ich bin noch zu blöd, um das vernünftig umzusetzen. An welcher Stelle soll ich denn meinen Listener einfügen? Habe jetzt einfach mal die Klasse kopiert.

1public class TaskListFragment extends ListFragment implements LoaderCallbacks<Cursor> {
2
3 private SimpleCursorAdapter mAdapter;
4 private long mRowId;
5 private CheckBox mTaskDone;
6
7 @Override
8 public void onCreate(Bundle savedInstanceState) {
9 super.onCreate(savedInstanceState);
10
11 String[] from = new String[] {
12 TaskProvider.COLUMN_TITLE,
13 TaskProvider.COLUMN_DONE
14 };
15
16 int[] to = new int[] {
17 R.id.txtView_taskname,
18 R.id.cb_taskdone
19 };
20
21 mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.task_row, null, from, to, 0);
22
23 mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
24 public boolean setViewValue(View view, Cursor c, int columnIndex) {
25 if(columnIndex == 3) {
26 CheckBox cb = (CheckBox) view;
27 cb.setChecked((c.getInt(c.getColumnIndex(TaskProvider.COLUMN_DONE))==0? false:true));
28 return true;
29 }
30 return false;
31 }
32 });
33
34 setListAdapter(mAdapter);
35 getLoaderManager().initLoader(0, null, this);
36 }
37
38 @Override
39 public void onViewCreated(View view, Bundle savedInstanceState) {
40 super.onViewCreated(view, savedInstanceState);
41 setEmptyText(getResources().getString(R.string.no_tasks));
42 registerForContextMenu(getListView());
43 setHasOptionsMenu(true);
44 }
45
46 @Override
47 public void onListItemClick(ListView l, View v, int position, long id) {
48 super.onListItemClick(l, v, position, id);
49 Intent i = new Intent(getActivity(), TaskEditActivity.class);
50 i.putExtra(TaskProvider.COLUMN_ROWID, id);
51 startActivity(i);
52 }
53
54 @Override
55 public Loader<Cursor> onCreateLoader(int ignored, final Bundle args) {
56 return new CursorLoader(getActivity(), TaskProvider.CONTENT_URI, null, null, null, null);
57 }
58
59 @Override
60 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
61 mAdapter.swapCursor(cursor);
62 }
63
64 @Override
65 public void onLoaderReset(Loader<Cursor> loader) {
66 mAdapter.swapCursor(null);
67 }
68}

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

20.03.2014, 17:33:41 via Website

An welcher stelle du den Listener einfügst ist eigentlich egal.
Denn der Code im Listener wird erst ausgeführt wenn das Ereignis eintritt.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
bazzey B.
  • Forum-Beiträge: 14

20.03.2014, 21:48:57 via Website

Guten Abend Pascal,

leider ist das aber nicht ganz so einfach. Leider lässt sich die App nach dem Einfügen des Listeners nicht mehr starten.

Listener

1@Override
2 public void onViewCreated(View view, Bundle savedInstanceState) {
3 super.onViewCreated(view, savedInstanceState);
4 setEmptyText(getResources().getString(R.string.no_tasks));
5 registerForContextMenu(getListView());
6 setHasOptionsMenu(true);
7
8
9 mTaskDone = (CheckBox) view.findViewById(R.id.cb_taskdone);
10
11 mTaskDone.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
12
13 @Override
14 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
15 Toast.makeText(getActivity(),
16 "Erfolgreich",
17 Toast.LENGTH_SHORT).show();
18 }
19 });
20 }

LogCat

03-20 16:44:10.924: E/AndroidRuntime(1365): FATAL EXCEPTION: main
03-20 16:44:10.924: E/AndroidRuntime(1365): Process: com.android.taskmanager, PID: 1365
03-20 16:44:10.924: E/AndroidRuntime(1365): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.taskmanager/com.android.taskmanager.TaskListActivity}: android.view.InflateException: Binary XML file line #23: Error inflating class fragment
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.os.Handler.dispatchMessage(Handler.java:102)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.os.Looper.loop(Looper.java:136)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.ActivityThread.main(ActivityThread.java:5017)
03-20 16:44:10.924: E/AndroidRuntime(1365): at java.lang.reflect.Method.invokeNative(Native Method)
03-20 16:44:10.924: E/AndroidRuntime(1365): at java.lang.reflect.Method.invoke(Method.java:515)
03-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-20 16:44:10.924: E/AndroidRuntime(1365): at dalvik.system.NativeStart.main(Native Method)
03-20 16:44:10.924: E/AndroidRuntime(1365): Caused by: android.view.InflateException: Binary XML file line #23: Error inflating class fragment
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
03-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.Activity.setContentView(Activity.java:1929)
03-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.taskmanager.TaskListActivity.onCreate(TaskListActivity.java:30)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.Activity.performCreate(Activity.java:5231)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
03-20 16:44:10.924: E/AndroidRuntime(1365): ... 11 more
03-20 16:44:10.924: E/AndroidRuntime(1365): Caused by: java.lang.NullPointerException
03-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.taskmanager.TaskListFragment.onViewCreated(TaskListFragment.java:82)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:906)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1082)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1184)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:291)
03-20 16:44:10.924: E/AndroidRuntime(1365): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
03-20 16:44:10.924: E/AndroidRuntime(1365): ... 21 more

Antworten
Andreas S.
  • Forum-Beiträge: 76

20.03.2014, 22:29:37 via Website

Hier in deinem Logcat steht praktisch alles:

103-20 16:44:10.924: E/AndroidRuntime(1365): Caused by: java.lang.NullPointerException
203-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.taskmanager.TaskListFragment.onViewCreated(TaskListFragment.java:82)

Die Frage ist nur was bei dir Zeile 82 in der Klasse ist.

— geändert am 20.03.2014, 22:34:20

bazzey B.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

21.03.2014, 13:07:36 via Website

Und im XML Fragment ist auch noch was Falsch:
1Caused by: android.view.InflateException: Binary XML file line #23: Error inflating class fragment

LG Pascal //It's not a bug, it's a feature. :) ;)

bazzey B.

Antworten
bazzey B.
  • Forum-Beiträge: 14

21.03.2014, 19:59:36 via Website

Hallo Andreas, danke dass du mich noch nicht aufgegeben hast.

Andreas S.
Hier in deinem Logcat steht praktisch alles:

103-20 16:44:10.924: E/AndroidRuntime(1365): Caused by: java.lang.NullPointerException
203-20 16:44:10.924: E/AndroidRuntime(1365): at com.android.taskmanager.TaskListFragment.onViewCreated(TaskListFragment.java:82)

Die Frage ist nur was bei dir Zeile 82 in der Klasse ist.

Zeile 82 ist hier Zeile 11. Im Debug-Modus habe ich auch gesehen, dass mTaskDone Null zugewiesen wird.

1@Override
2 public void onViewCreated(View view, Bundle savedInstanceState) {
3 super.onViewCreated(view, savedInstanceState);
4 setEmptyText(getResources().getString(R.string.no_tasks));
5 registerForContextMenu(getListView());
6 setHasOptionsMenu(true);
7
8
9 mTaskDone = (CheckBox) view.findViewById(R.id.cb_taskdone);
10
11 mTaskDone.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
12
13 @Override
14 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
15 Toast.makeText(getActivity(),
16 "Erfolgreich",
17 Toast.LENGTH_SHORT).show();
18 }
19 });

Antworten
impjor
  • Forum-Beiträge: 1.793

21.03.2014, 20:14:34 via Website

Anscheinend befindet sich in der View view keine View, die die id R.id.cb_taskdone besitzt, daher wird nichts gefunden = null zugewiesen.

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

bazzey B.

Antworten
bazzey B.
  • Forum-Beiträge: 14

21.03.2014, 20:51:19 via Website

Ja, genau das war es. So ganz habe ich es zwar immer noch nicht verstanden, weil ich im konkreten Fall das Problem nicht lösen könnte. Aber da bei onCreate ja sowieso die Checkbox initialisiert wird und ich den Listener überall einsetzen darf, habe ich ihn einfach dort mit angehangen. :lol:

1@Override
2 public void onCreate(Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4
5 // Einen Array erzeugen, um die in der Liste anzuzeigenden Felder anzugeben (nur TITLE), S. 311
6 String[] from = new String[] {
7 TaskProvider.COLUMN_TITLE,
8 TaskProvider.COLUMN_DONE
9 };
10
11 // ... und einen Array der Felder, mit denen dieseFelder verbunden werden sollen, S.311
12 int[] to = new int[] {
13 R.id.txtView_taskname,
14 R.id.cb_taskdone
15 };
16
17 // Nun wird ein SimpleCursorAdapter erzeugt und auf display gesetzt, S.311
18 mAdapter = new SimpleCursorAdapter(getActivity(), R.layout.task_row, null, from, to, 0);
19
20 mAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
21 public boolean setViewValue(View view, Cursor c, int columnIndex) {
22 if(columnIndex == 3) {
23 CheckBox cb = (CheckBox) view;
24 cb.setChecked((c.getInt(c.getColumnIndex(TaskProvider.COLUMN_DONE))==0? false:true));
25 cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
26 @Override
27 public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
28 Toast.makeText(getActivity(),
29 "Erfolgreich",
30 Toast.LENGTH_SHORT).show();
31 }
32 });

33 return true;
34 }
35 return false;
36 }
37 });

Danke!!! Ihr seid meine Helden. Toller Start ins Wochenende.

Antworten
bazzey B.
  • Forum-Beiträge: 14

24.03.2014, 22:58:28 via Website

Hallo impjor und alle anderen Leser,

wie du vielleicht schon gesehen hast, ist die grundsätzliche Frage geklärt.

Aber das Abspeichern des Checkbox-Status in der Datenbank ist gar nicht so einfach wie ich dachte. Die ID des Datensatzes ist nicht so einfach zu erfassen. Ich finde leider nicht entsprechendes im Netz. Kann mir jemand vielleicht einen Typ geben?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

25.03.2014, 07:09:45 via App

Welche id meinst du?
Die des datensetzes in der Db oder die id der checxkbox?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
bazzey B.
  • Forum-Beiträge: 14

25.03.2014, 07:33:00 via App

Guten Morgen, die Id des Datensatzes in der DB meine ich.

Antworten
SvenDD
  • Forum-Beiträge: 272

25.03.2014, 07:42:45 via Website

Wie sieht den deine Tabelle in der DB dafür aus? Du erfasst doch den Datensatz, da kannst du doch auch den Status der Checkbox mit speichern ansonsten mittels Foreign Key mit deiner Datensatztabelle verknüpfen.

Antworten
bazzey B.
  • Forum-Beiträge: 14

27.03.2014, 11:22:04 via Website

Vielen Dank für den Hinweis. Ich habe es tatsächlich hinbekommen. Mir hat einfach noch ein Wissen von der Materie gefehlt. Aber jetzt geht es... :D Danke noch mal für alle geduldigen Unterstützern.

Antworten