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

Anfängerproblem

Dieses Thema im Forum "Android App Entwicklung" wurde erstellt von eddie7, 01.02.2011.

  1. eddie7, 01.02.2011 #1
    eddie7

    eddie7 Threadstarter Neuer Benutzer

    Beiträge:
    16
    Erhaltene Danke:
    0
    Registriert seit:
    30.11.2010
    Hi,

    ich habe ein Beispiel aus Beginning Android modfifiziert, um eine ListView mit EditText zu kreieren. Es soll lediglich eine Liste mit einem Text und einem editierbaren Feld pro Zeile angezeigt werden.

    Leider hab ich da noch ein paar Verständnisprobleme, die mich schon einge Stunden quälen. :)
    Das Original hatte statt dem EditText eine RatingBar und funktioniert einwandfrei. Meine Version sieht ok aus, bis ich anfange zu scrollen. Dann kommen die angezeigten Werte durcheinander.
    Beim Debuggen sehe ich, dass getView im AusgabenWrapper beim Scrollen nach unten eine View übergeben bekommt, wenn man den sichtbaren Bereich verlässt, obwohl da meiner Meinung nach noch keine existieren dürfte, und von da ab ist alles durcheinander.

    Da das ein bißchen unverständlich sein dürfte, ist unten der Code.

    Wäre für nen Tipp, was ich da falsch mache, wirklich dankbar. Auch ein RTFM mit link zu einem passenden Beispiel wäre hilfreich, ich habe schon nach Beispielen gegoogled, aber nichts Passenderes gefunden.
    Bin ziemlich unerfahren, was Oberflächenprogrammierung (sprich MVC) angeht.
    Ich vermute, dass die Lösung ganz trivial ist..

    Ach ja, die 2. Frage:
    wenn ich in diesem Beispiel in ein EditText klicke,verliere ich erst mal den Focus, wenn die Tastatur aufgeht und muss noch mal reinklicken, um editieren zu können. Dass ich nicht editieren kann, ist höchstwahrscheinlich eine Folge des obigen Problems mit getView.


    Viele Grüße,
    Eddie

    AusgabenWrapper.java
    Code:
    package com.commonsware.android.fancylists.seven;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.ListAdapter;
    
    public class AusgabenWrapper extends AdapterWrapper {
        Context ctxt=null;
        String[] rates=null;
        
        public AusgabenWrapper(Context ctxt, ListAdapter delegate) {
            super(delegate);
            
            this.ctxt=ctxt;
            this.rates=new String[delegate.getCount()];
            
            for (int i=0;i<delegate.getCount();i++) {
                this.rates[i]=(String) getItem(i);
            }
        }
        
        public View getView(int position, View convertView,
                                                ViewGroup parent) {
            ViewWrapper wrap=null;
            View row=convertView;
                                                            
            if (convertView==null) {
                LinearLayout layout=new LinearLayout(ctxt);
                EditText editText=new EditText(ctxt);
                
                editText.setTag(new Integer(position));
                editText.setText(rates[position]);
                
                View guts=delegate.getView(position, null, parent);
            
                layout.setOrientation(LinearLayout.HORIZONTAL); 
                        
                editText.setLayoutParams(new LinearLayout.LayoutParams(
                            LinearLayout.LayoutParams.WRAP_CONTENT,
                            LinearLayout.LayoutParams.FILL_PARENT));
                guts.setLayoutParams(new LinearLayout.LayoutParams(
                            LinearLayout.LayoutParams.FILL_PARENT,
                            LinearLayout.LayoutParams.FILL_PARENT));
                
                        
                layout.addView(editText);                     
                layout.addView(guts);
                
                wrap=new ViewWrapper(layout);
                wrap.setGuts(guts);
                layout.setTag(wrap);
                
                row=layout;                
            }
            else {
                wrap=(ViewWrapper)convertView.getTag();
                wrap.setGuts(delegate.getView(position, wrap.getGuts(), parent));
            }
            
            return(row);
        }        
    }
    ViewWrapper.java:
    Code:
    package com.commonsware.android.fancylists.seven;
    
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.EditText;
    
    class ViewWrapper {
        ViewGroup base;
        View guts=null;
        EditText rate=null;
        
        ViewWrapper(ViewGroup base) {
            this.base=base;
        }
        
        EditText getText() {
            if (rate==null) {
                rate=(EditText)base.getChildAt(0);
            }
            
            return(rate);
        }
        
        void setEditText(EditText rate) {
            this.rate=rate;
        }
        
        View getGuts() {
            if (guts==null) {
                guts=base.getChildAt(1);
            }
            
            return(guts);
        }
        
        void setGuts(View guts) {
            this.guts=guts;
        }
    }
    
    AusgabenListView.java:
    Code:
    /***
        Copyright (c) 2008-2009 CommonsWare, LLC
        
        Licensed under the Apache License, Version 2.0 (the "License"); you may
        not use this file except in compliance with the License. You may obtain
        a copy of the License at
            http://www.apache.org/licenses/LICENSE-2.0
        Unless required by applicable law or agreed to in writing, software
        distributed under the License is distributed on an "AS IS" BASIS,
        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        See the License for the specific language governing permissions and
        limitations under the License.
    */
    
    package com.commonsware.android.fancylists.seven;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.widget.ListAdapter;
    import android.widget.ListView;
    
    public class AusgabenListView extends ListView {
        public AusgabenListView(Context context) {
            super(context);
        }
        
        public AusgabenListView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
                                        
        public AusgabenListView(Context context, AttributeSet attrs,
                                                    int defStyle) {
            super(context, attrs, defStyle);
        }
        
        public void setAdapter(ListAdapter adapter) {
            super.setAdapter(new AusgabenWrapper(getContext(), adapter));
        }
    }
    Ausgaben.java:
    Code:
    package com.commonsware.android.fancylists.seven;
    
    import android.app.ListActivity;
    import android.os.Bundle;
    import android.widget.ArrayAdapter;
    
    public class Ausgaben extends ListActivity {
        String[] items={"null", "eins", "zwei", "drei", "vier", "fünf",
                        "sechs", "sieben", "acht", "neun", "zehn",
                        "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn",
                        "sechzehn", "siebzehn", "achtzehn", "neunzehn", "zwanzig"};
        
        @Override
        public void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            setContentView(R.layout.main);
            
            setListAdapter(new ArrayAdapter<String>(this,
                                                    android.R.layout.simple_list_item_1,
                                                    items));
        }
    }
    
    AdapterWrapper.java:
    Code:
    package com.commonsware.android.fancylists.seven;
    
    import android.database.DataSetObserver;
    import android.widget.ListAdapter;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.ViewGroup;
    
    public class AdapterWrapper implements ListAdapter {
        ListAdapter delegate=null;
        
        public AdapterWrapper(ListAdapter delegate) {
            this.delegate=delegate;
        }
        
        public int getCount() {
            return(delegate.getCount());
        }
        
        public Object getItem(int position) {
            return(delegate.getItem(position));
        }
        
        public long getItemId(int position) {
            return(delegate.getItemId(position));
        }
        
        public View getView(int position, View convertView,
                                                ViewGroup parent) {
            return(delegate.getView(position, convertView, parent));
        }
        
        public void registerDataSetObserver(DataSetObserver observer) {
            delegate.registerDataSetObserver(observer);
        }
        
        public boolean hasStableIds() {
            return(delegate.hasStableIds());
        }
        
        public boolean isEmpty() {
            return(delegate.isEmpty());
        }
        
        public int getViewTypeCount() {
            return(delegate.getViewTypeCount());
        }
        
        public int getItemViewType(int position) {
            return(delegate.getItemViewType(position));
        }
        
        public void unregisterDataSetObserver(DataSetObserver observer) {
            delegate.unregisterDataSetObserver(observer);
        }
        
        public boolean areAllItemsEnabled() {
            return(delegate.areAllItemsEnabled());
        }
        
        public boolean isEnabled(int position) {
            return(delegate.isEnabled(position));
        }
    }
    
    main.xml:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <com.commonsware.android.fancylists.seven.AusgabenListView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/list"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent"
        android:drawSelectorOnTop="false"
    />
    
    AndroidManifest.xml:
    Code:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.commonsware.android.fancylists.seven">
            <application android:label="@string/app_name"
                    android:icon="@drawable/cw">
                    <activity android:name=".Ausgaben" android:label="@string/app_name">
                            <intent-filter>
                                    <action android:name="android.intent.action.MAIN" />
                                    <category android:name="android.intent.category.LAUNCHER" />
                            </intent-filter>
                    </activity>
            </application>
    </manifest>
     
  2. Bobert, 02.02.2011 #2
    Bobert

    Bobert Erfahrener Benutzer

    Beiträge:
    161
    Erhaltene Danke:
    15
    Registriert seit:
    21.11.2010
    Phone:
    Nexus S
    Hallo,

    gerne helfe ich!

    Reduziere dein Problem mal :D. Wenn ich kann antworte ich!:thumbsup:

    Grüße Bobert
     
  3. eddie7, 02.02.2011 #3
    eddie7

    eddie7 Threadstarter Neuer Benutzer

    Beiträge:
    16
    Erhaltene Danke:
    0
    Registriert seit:
    30.11.2010
    Reduzieren - das hab ich befürchtet. :)

    Im Code kann ich nichts weglassen, da ich mir nicht sicher bin, wo das Problem ist. Ich versuche aber mal, das Problem zu beschreiben.

    Ich will nur eine Liste anzeigen, die pro Zeile ein EditText und ein TextView enthält, befüllt aus einem array von Strings.
    Das sieht beim Programmstart auch ganz gut aus. Wenn ich aber scrolle, ist der Inhalt ab der 9. zeile im EditText falsch, in der TextView richtig. Da kommt irgenwas durcheinander.
    Was mich verwirrt, ist, dass getView in AusgabenWrapper für die falsch dargestellten Zeilen bereits beim 1. Aufruf eine View (convertView) erhält, obwohl da meiner Meinung nach noch keine View dafür da sein dürfte - für die ersten 8 Zeilen wird beim ersten Aufruf von getView korrekt null (keine View) geliefert. Oder verstehe ich da getView falsch?
    Die Inhalte der EditText-Felder ab der 9. Zeile sind identisch mit denen ab der 1. Zeile (10. = 2. usw.). Wenn ich dann wieder nach oben scrolle, sind die Inhalte der EditText-Komponenten total durcheinander.

    Ich hoffe, ich habe mich einigermaßen verständlich ausgedrückt...

    Viele Grüße,
    Eddie
     
  4. Fr4gg0r, 03.02.2011 #4
    Fr4gg0r

    Fr4gg0r App-Anbieter (Werbung)

    Beiträge:
    2,506
    Erhaltene Danke:
    447
    Registriert seit:
    21.12.2009
    EditTexte in ner ListView.. damit hatte ich mich auch mal rumgeschlagen.. hab dann letztendlich auf ScrollView umgestellt.
    Bin auf ne Lösung gespannt. :)
     
  5. eddie7, 08.02.2011 #5
    eddie7

    eddie7 Threadstarter Neuer Benutzer

    Beiträge:
    16
    Erhaltene Danke:
    0
    Registriert seit:
    30.11.2010
    Hier meine Lösung (zusammengebastelt aus verschiedenen Codeschnipseln im Netz):

    Die Klasse, die die Werte hält:
    Code:
    public class Ausgabe {
      String item;
      String betrag;
        
        Ausgabe(String item, String betrag) {
        this.item = item;
        this.betrag = betrag;
        }
    
      public String getItem() {
        return item;
      }
    
      public void setItem(String item) {
        this.item = item;
      }
    
      public String getBetrag() {
        return betrag;
      }
    
      public void setBetrag(String betrag) {
        this.betrag = betrag;
      }
    }
    
    Die Activity:
    Code:
    public class Eingabe extends ListActivity {
      String[] items =
          { "null", "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf",
              "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24" };
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.ausgaben_overview);
    
        final List<Ausgabe> ausgaben = new ArrayList<Ausgabe>();
        for (int i = 0; i < items.length; i++) {
          Ausgabe ausgabe = new Ausgabe(items[i], items[i] + "Test");
          ausgaben.add(ausgabe);
        }
    
        setListAdapter(new AusgabenAdapter(this, R.layout.eintrag, ausgaben));
      }
    }
    
    Der abgeleitete Adapter:
    Code:
    public class AusgabenAdapter extends BaseAdapter {
      private final Context context;
      private final List<Ausgabe> ausgaben;
      private final int rowResID;
      private final LayoutInflater layoutInflater;
    
      public AusgabenAdapter(final Context context, final int rowResID, final List<Ausgabe> ausgaben) {
        this.context = context;
        this.rowResID = rowResID;
        this.ausgaben = ausgaben;
    
        layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      }
    
      public int getCount() {
        return ausgaben.size();
      }
    
      public Object getItem(int position) {
        return ausgaben.get(position);
      }
    
      public long getItemId(int position) {
        return position;
      }
    
      public View getView(final int position, View convertView, ViewGroup parent) {
    
        final ViewHolder viewHolder;
        final Ausgabe ausgabe;
    
        if (convertView == null) {
          viewHolder = new ViewHolder();
          ausgabe = ausgaben.get(position);
          convertView = layoutInflater.inflate(rowResID, null);
          viewHolder.item = (EditText) convertView.findViewById(R.id.item);
          viewHolder.item.addTextChangedListener(new TextWatcher() {
            public void afterTextChanged(Editable edit) {
              ausgaben.get(viewHolder.ref).setItem(edit.toString());
            }
    
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
            }
    
            public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
              // attitude_values[ref] = Attitude_Value.getText().toString();
            }
          });
    
          viewHolder.betrag = (TextView) convertView.findViewById(R.id.betrag);
          viewHolder.betrag.setText(ausgabe.getBetrag());
          convertView.setTag(viewHolder);
        } else {
          viewHolder = (ViewHolder) convertView.getTag();
        }
    
        viewHolder.ref = position;
        viewHolder.item.setText(ausgaben.get(position).getItem());
        viewHolder.betrag.setText(ausgaben.get(position).getBetrag());
        return convertView;
      }
    
      class ViewHolder {
          TextView betrag;
          EditText item; 
          int ref;
      }
    }
    
    Das Problem war: ListView hält nicht so viele Einträge, wie es darzustellende Daten gibt. Deswegen werden views wiederverwendet und müssen mit korrekten Daten gesetzt werden. Die richtigen Daten werden anhand der position bestimmt und in ref im ViewHolder gehalten. Geänderte Daten werden mit einem TextWatcher gesichert.

    Vielleicht hilfts ja jemandem...

    Gruß,
    Eddie
     

Diese Seite empfehlen