1. Nimm jetzt an unserem 2. ADVENT-Gewinnspiel teil - Alle Informationen findest Du hier!

Menü bei OnClick

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von Micka, 12.01.2012.

  1. Micka, 12.01.2012 #1
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    Hy,

    ich arbeite gerade an einer App die unter anderem eine Activity besitzt, die ListActivity implementiert. Mittels eigenem ListAdapter ist es mir bereits gelungen die Daten für die Liste aus einer Datenbank zu lesen.

    So weit so gut.

    Mein Wunsch ist es nun das sich ein Menü(meinetwegen ein KontextMenu) öffnet wenn man auf eines der Elemente(Alles TextViews) des ListView klickt.

    Mit einem normalen KontextMenu bin ich nicht weit gekommen. Problem dabei ist das ich in der Methode
    Code:
    public boolean onContextItemSelected(MenuItem item)
    nicht mehr auf die ID der Datenbankzeile zugreifen kann aus der das item ursprünglich kam.

    Also habe ich mir gedacht ich setze einfach im Layout der Listview bei den einzelnen Views das folgende Attribut.
    Code:
    android:onClick="beliebigeOnClickMethode"
    Nachdem der eigeneListAdapter die Textviews dann mit ihrem Inhalt aus der Datenbank befüllt hat setze ich per
    Code:
    setID()
    noch schnell die ID des Textviews auf die ID der Datenbankzeile.

    nun könnte ich in meiner Activity in der Methode bequem auf die Id zugreifen.

    Beispiel:
    Code:
    public void beliebigeOnClickMethode(View v)
    {
        Textview textview = (Textview) view;
        int id = textview.getID();
    }
    
    damit könnte ich nun arbeiten um z.B: in der Datenbank eine Zeile zu löschen oder zu ändern. Aber eben das oder ist das Problem.

    Wie kriege ich ein Menü hin das nun zwischen den zwei Fällen(EDIT, DELETE) entscheidet?

    Das normale OptionsMenü der Activity scheidet aus da es bereits anderweitig genutzt ist.
     
  2. swordi, 12.01.2012 #2
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    du kannst mittels meniiteminfo auf die position der geklickten zeile innerhalb deiner onContextItemSelected zugreifen.

    such mal danach
     
    Micka bedankt sich.
  3. Micka, 13.01.2012 #3
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    okay, werd mir das mal raussuchen. Einen eigenen Menüartigen Dialog in der onClickMethode kann ich nicht erzeugen oder gibt es dafür auch eine Möglichkeit?
     
  4. Micka, 13.01.2012 #4
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    Mir ist gerade eine eventuelle Lösung mittels Kontextmenü eingefallen.
    Der List Adapter nutzt ja eine ArrayList. Wenn ich ihm nun eine angepasste ArrayList gebe kann ich mir getItemId so implementieren das die DatenbankId returned wird. Werde mal sehen was ich später noch hinkriege.
     
  5. swordi, 13.01.2012 #5
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    ich sag dir ja - du kannst ein contextmenu implementieren, dort über menuiteminfo die position des geklickten finden und dann vom adapter laden.

    registerForContextMenu(listview); nicht vergessen
     
    Micka bedankt sich.
  6. Micka, 13.01.2012 #6
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    Ich hab gerade in der S-Bahn nochmal gegoogelt und folgendes gefunden.
    ContextMenü mit ListView verbinden und Daten übergeben. - Tutorials & FAQs - Android-Developers
    Es scheint also eine Lösung für mein Problem zu geben. Allerdings verstehe ich an dieser Lösung einiges nicht, ohne es zu verstehen will ich es nicht implementieren.

    Was bewirkt startManagingCursor z.B.,

    Desweiteren ist mir mit einem simpleCursorAdapter nicht geholfen. Ich müsste das ganze auf meinen Code anpassen.

    Kann jemand von euch den gesamten Code nachvollziehen?
     
  7. samarek, 13.01.2012 #7
    samarek

    samarek Android-Hilfe.de Mitglied

    Beiträge:
    101
    Erhaltene Danke:
    2
    Registriert seit:
    24.10.2011
    Also hier ist erstmal was "startManagingCursor" tut
    Activity | Android Developers

    und deine Frage aus dem ersten Post verstehe ich nicht so ganz, zu den ContextMenus gibt es doch die onContextItemSelected(MenuItem item), da kannst du doch dann wieder ganz einfach unterscheiden welche Option im Kontextmenü gewählt wurde.

    Beantwortet das deine Frage? oder was wolltest du wissen?
     
    Micka bedankt sich.
  8. swordi, 13.01.2012 #8
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009

    er nutzt halt einen CursorAdapter, das musst ja nicht. für dich interessant ist eher folgendes

    info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

    info.position

    und schon hast die ausgewählte listen position. dann nur noch vom adapter das objekt holen und schon hast alles was du brauchst ( je nachdem was dein adapter für daten hält )

    ist ja jetzt echt nicht so ne große herausforderung oder ?
     
    Micka bedankt sich.
  9. Micka, 13.01.2012 #9
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    @samarek das gewählte Menuitem zu finden ist kein Problem aber die Id des Datenbankeintrags der dahinter steckt ist knifflig.

    @swordi greift info.position auf die Methode GetItemId des ListAdapters zu oder woher kennt AdapterView.AdapterContextMenuInfo die id des Eintrags in der Datenbank?

    Oder gibt info.position mir die id des TextViews das geklickt wurde?
     
  10. swordi, 13.01.2012 #10
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    info.position ist, wie der name schon sagt, die position in der liste

    position = 3 wird das dritte element sein.

    einfach getItem(position) aufrufen und du bekommst das item aus dem adapter. logisch oder?
     
    Micka bedankt sich.
  11. Micka, 14.01.2012 #11
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    Gut. Aber die position in der Array List des Adapters stimmt nicht immer mit drr id in der Datenbank überein. Werde am Sonntag wieder an der App arbeiten und dann berichten.
     
  12. swordi, 14.01.2012 #12
    swordi

    swordi Gewerbliches Mitglied

    Beiträge:
    3,389
    Erhaltene Danke:
    441
    Registriert seit:
    09.05.2009
    tja wie auch schon öfters hier geschrieben.

    du gibst doch dem adapter deine daten, dann gib ihm ein objekt, welches auch die datenbank id enthält.

    mit getItem(pos) holst dir das objekt und liest die db id.

    ein wenig eigeninitiative
     
    Micka bedankt sich.
  13. Micka, 15.01.2012 #13
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    Genau so hab ich es mir gedacht swordi. Aber irgendwie scheint es nicht zu klappen. Wenn ich getItem(info.position) aufrufe wird eine ArrayIndexOutOfBoundException geschmissen.

    Ich poste hier mal meinen Adapter, meine Activity und den LogCatOutput.
    Durch Unterstreichung und Fettdruck hervorgehoben:
    - Zeilenangaben im LogCat
    - Betreffende Zeile in der Activity
    - Betreffende Zeile im ListAdapter

    Meine Activity: (EintraegeAnzeigenActivity.java)
    Code:
    package micka.haushaltsbuch;
    
    import java.util.ArrayList;
    import android.app.ListActivity;
    import android.content.Intent;
    import android.database.Cursor;
    import android.database.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.ContextMenu;
    import android.view.ContextMenu.ContextMenuInfo;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.AdapterView.AdapterContextMenuInfo;
    import android.widget.AdapterView.OnItemLongClickListener;
    import android.widget.EditText;
    import android.widget.ListView;
    import android.widget.RadioGroup;
    import android.widget.SimpleCursorAdapter;
    import android.widget.Spinner;
    
    public class EintraegeAnzeigenActivity extends ListActivity
    {
        final static String MY_DB_NAME = "FinanzenDB";
        static String MY_DB_TABLE = "eintraege";
        private static final int COLUMN_INDEX_TITLE = 1; //Titel des Contextmenüs
        SQLiteDatabase myDB;
        final static String tag="ensacom"; 
        private EintragListAdapter mAdapter;
        private ArrayList<Eintrag> mData = new ArrayList<Eintrag>();
        
            
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            
            initiateData();
            final Bundle extras = getIntent().getExtras();
            if(extras != null)
            {
                MY_DB_TABLE = extras.getString(StartHaushaltsbuchActivity.TABELLENNAME);
            }
            mAdapter = new EintragListAdapter(this, mData);
            View header = getLayoutInflater().inflate(R.layout.eintraegetitellayout, null);
            ListView listView = getListView();
            registerForContextMenu(listView);
            listView.addHeaderView(header);
            this.setListAdapter(mAdapter);
        }
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v,
                                        ContextMenuInfo menuInfo) {
          super.onCreateContextMenu(menu, v, menuInfo);
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.eintragcontext, menu);
        }
        @Override
        public boolean onContextItemSelected(MenuItem item) {
          AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
          long id;
          switch (item.getItemId()) {
          case R.id.eintrag_context_bearbeiten:
              [U][B]id = mAdapter.getItemId(info.position);[/B] [B]//Zeile 69[/B][/U]
              eintragLoeschen(id);
              finish();
              return true;
          case R.id.eintrag_context_loeschen:
              return true;
          default:
            return super.onContextItemSelected(item);
          }
        }
        private void eintragLoeschen(long id)
        {
            final Bundle extras = getIntent().getExtras();
            if(extras != null)
            {
                MY_DB_TABLE = extras.getString(StartHaushaltsbuchActivity.TABELLENNAME);
            }
            myDB = null;
            myDB = this.openOrCreateDatabase(MY_DB_NAME, MODE_PRIVATE, null);
            try
            {    
                System.out.println(id);
                myDB.execSQL("DELETE FROM " + MY_DB_TABLE+ " WHERE _id=" + id + ";");
            }catch(SQLException esql)
            {
                System.out.println(esql.toString());
            }
            myDB.close();
        }
        public void eintragBearbeiten(View v)
        {
            
        }
        private void initiateData()
        {
            myDB = null;
            final Bundle extras = getIntent().getExtras();
            if(extras != null)
            {
                MY_DB_TABLE = extras.getString(StartHaushaltsbuchActivity.TABELLENNAME);
            }
            Eintrag eintrag;
            myDB = this.openOrCreateDatabase(MY_DB_NAME, MODE_PRIVATE, null);
            
                Cursor eintragCursor = myDB.rawQuery("SELECT _id, day, month, year, wofuer, betrag FROM " + MY_DB_TABLE + " Order By day, month, year", null);
                
                eintragCursor.moveToFirst();            
                
                
                if(eintragCursor.moveToFirst())
                {
                    do
                    {
                        eintrag = null;
                        eintrag = new Eintrag(eintragCursor.getInt(0),eintragCursor.getInt(1),eintragCursor.getInt(2),eintragCursor.getInt(3),eintragCursor.getString(4),eintragCursor.getDouble(5));
                        mData.add(eintrag);
                            
                        eintragCursor.moveToNext();
                    }while(eintragCursor.isAfterLast() == false);
                }
                eintragCursor.close();
                myDB.close();
        }
    }
    
    Mein ListAdapter: (EintragListAdapter.java)
    Code:
    package micka.haushaltsbuch;
    
    import java.util.ArrayList;
    
    import android.app.ListActivity;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
    
    public class EintragListAdapter extends BaseAdapter
    {
        private ArrayList<Eintrag> mData = new ArrayList<Eintrag>();
        
        private final LayoutInflater mLayoutInflater;
    
        public EintragListAdapter(Context pContext, ArrayList<Eintrag> pData)
        {
                        mData = pData;
                        mLayoutInflater = (LayoutInflater) pContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
        public int getCount() 
        {
            return mData.size();
        }
        public Object getItem(int pPosition) 
        {
            return mData.get(pPosition);
        }
        public long getItemId(int pPosition) 
        {
            [U][B]Eintrag eintrag = mData.get(pPosition); //Zeile 38[/B][/U]
            return eintrag._id;
        }
        public void changeData(ArrayList<Eintrag> pData)
        {
            mData = pData;
            this.notifyDataSetChanged();
        }
        
        public View getView(int pPosition, View convertView, ViewGroup parent) 
        {
            if (convertView == null) 
            {
                convertView = mLayoutInflater.inflate(R.layout.eintraegeanzeigenlayout, null);
            }
            String datum;
            String day = String.valueOf(((Eintrag)getItem(pPosition)).day);
            String month = String.valueOf(((Eintrag)getItem(pPosition)).month);
            String year = String.valueOf(((Eintrag)getItem(pPosition)).year);
            datum = day + "." + month + "." + year;
            ((TextView) convertView.findViewById(R.id.eintraegeAnzeigenDatum)).setText(datum);
            ((TextView) convertView.findViewById(R.id.eintraegeAnzeigenDatum)).setId(((Eintrag)getItem(pPosition))._id);
            ((TextView) convertView.findViewById(R.id.eintraegeAnzeigenZweck)).setText(((Eintrag)getItem(pPosition)).wofuer);
            ((TextView) convertView.findViewById(R.id.eintraegeAnzeigenZweck)).setId(((Eintrag)getItem(pPosition))._id);
            String betrag = String.valueOf(((Eintrag)getItem(pPosition)).betrag);
            ((TextView) convertView.findViewById(R.id.eintraegeAnzeigenBetrag)).setText(betrag);
            ((TextView) convertView.findViewById(R.id.eintraegeAnzeigenBetrag)).setId(((Eintrag)getItem(pPosition))._id);;
            
            return convertView;
        }
        
    }
    
    
    LogCat:
    Code:
    01-15 14:08:45.453: W/KeyCharacterMap(320): No keyboard for id 0
    01-15 14:08:45.453: W/KeyCharacterMap(320): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
    01-15 14:08:52.532: D/dalvikvm(320): GC_FOR_MALLOC freed 6183 objects / 311624 bytes in 75ms
    01-15 14:08:52.602: V/ensacom(320): Insert new Eintrag: 1.1.2011, 1, 1.0
    01-15 14:09:10.703: D/AndroidRuntime(320): Shutting down VM
    01-15 14:09:10.703: W/dalvikvm(320): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
    01-15 14:09:10.733: E/AndroidRuntime(320): FATAL EXCEPTION: main
    [U][B]01-15 14:09:10.733: E/AndroidRuntime(320): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
    [/B][B]01-15 14:09:10.733: E/AndroidRuntime(320):     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:257)[/B][/U]
    01-15 14:09:10.733: E/AndroidRuntime(320):     at java.util.ArrayList.get(ArrayList.java:311)
    [U][B]01-15 14:09:10.733: E/AndroidRuntime(320):     at micka.haushaltsbuch.EintragListAdapter.getItemId(EintragListAdapter.java:38)[/B][/U]
    [U][B]01-15 14:09:10.733: E/AndroidRuntime(320):     at micka.haushaltsbuch.EintraegeAnzeigenActivity.onContextItemSelected(EintraegeAnzeigenActivity.java:69)
    [/B][/U]01-15 14:09:10.733: E/AndroidRuntime(320):     at android.app.Activity.onMenuItemSelected(Activity.java:2199)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback.onMenuItemSelected(PhoneWindow.java:2744)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:143)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:855)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.view.menu.MenuDialogHelper.onClick(MenuDialogHelper.java:137)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:874)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.widget.AdapterView.performItemClick(AdapterView.java:284)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.widget.ListView.performItemClick(ListView.java:3382)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:1696)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.os.Handler.handleCallback(Handler.java:587)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.os.Handler.dispatchMessage(Handler.java:92)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.os.Looper.loop(Looper.java:123)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at android.app.ActivityThread.main(ActivityThread.java:4627)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at java.lang.reflect.Method.invokeNative(Native Method)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at java.lang.reflect.Method.invoke(Method.java:521)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
    01-15 14:09:10.733: E/AndroidRuntime(320):     at dalvik.system.NativeStart.main(Native Method)
    Sieht jemand wo das Problem liegt?
     
  14. Micka, 15.01.2012 #14
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    Vielleicht ist die Klasse Eintrag auch noch interessant, daher hier noch schnell die Klasse.

    Code:
    package micka.haushaltsbuch;
    
    public class Eintrag 
    {
        int _id;
        int day;
        int month;
        int year;
        String wofuer;
        double betrag;
        
        public Eintrag(int id,int tag, int monat, int jahr, String zweck, double betrag)
        {
            this._id = id;
            this.day = tag;
            this.month = monat;
            this.year = jahr;
            this.wofuer = zweck;
            this.betrag = betrag;
        }
        public Eintrag()
        {
            
        }
    }
    
    
     
  15. Micka, 16.01.2012 #15
    Micka

    Micka Threadstarter Erfahrener Benutzer

    Beiträge:
    173
    Erhaltene Danke:
    1
    Registriert seit:
    30.12.2011
    So, nach einer Mütze schlaf habe ich nun etwas anderes probiert und siehe da, es klappt. Mein Problem ist also Offiziell gelöst.

    Code:
    public boolean onContextItemSelected(MenuItem item) 
        {
          AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
          switch (item.getItemId()) {
          case R.id.eintrag_context_bearbeiten:
               [B]eintragBearbeiten(info.id);[/B]
              finish();
              return true;
          case R.id.eintrag_context_loeschen:
              eintragLoeschen(info.id);
              finish();
              return true;
          default:
            return super.onContextItemSelected(item);
          }
        }
    Warum wieso weshalb der voherige Versuch über die Position das Objekt zu kriegen nicht geklappt hat würde mich jedoch dennoch interessieren, eilt aber nicht.

    Danke nochmal an alle, die ein Teil ihrer Zeit investiert haben um mir zu helfen.
     

Diese Seite empfehlen