0

我尝试在 Stackoverflow 上发布我的代码,但我认为这有太多错误需要修复。

因此,由于我最大的问题是误解,所以我只是询问我必须开发它的方式。

问题:我想做一个由自定义 cursorAdapter 提供的 listView。

为什么要自定义 cursorAdapter ?

因为现在,我想在 listView 的第一行有一个 editText,然后是数据库中的项目,然后在 listView 的最后一行有另一个 editText。我可以用页眉和页脚来解决它,但后来我想在同一个 listView 中有许多其他行模板,甚至可能有很多光标,这就是原因。

按照本教程,我尝试在适配器中使用多种类型关于在一个列表视图中拥有多种行类型的链接

当然我重写了bindView 和newView。

它失败了。我有很多错误,比如我不知道如何直接将editText添加到我的listView等......对我来说最大的问题是理解,我只需要解释如何做到这一点,我的意思是我应该做什么在 bindView 中,我究竟应该在 newView 中做什么。

好的,我改变了主意,这是我的适配器的代码。小心,这可能很可怕。

    package com.android.activity;


import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.TextView;

public class NotesCursorAdapter extends CursorAdapter{

    private Context context;
    //  private Cursor cursor;
    private int addNoteTopPosition = 0;
    private int addNoteBottomPosition;
    private LayoutInflater inflater;

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_ADD_NOTE_BOTTOM = 1;
    private static final int TYPE_ADD_NOTE_TOP = 2;
    private static final int TYPE_MAX_COUNT = TYPE_ADD_NOTE_TOP + 1;

    public NotesCursorAdapter (Context context, Cursor cursor, int flag){
        super(context, cursor);
        this.context = context;
        addNoteTopPosition = 0;
        addNoteBottomPosition = cursor.getCount()+1;

        inflater = LayoutInflater.from(this.context);

    }

    //  public 

    @Override
    public int getCount() {  
        return super.getCount() + 2;
    } 





    @Override
    public View getView(int position, View convertView, ViewGroup parent){
        ViewHolder holder = null;
        int type = getItemViewType(position);
        if (convertView == null) {
            holder = new ViewHolder();
            switch (type) {

            case TYPE_ADD_NOTE_TOP:
                convertView = inflater.inflate(R.layout.add_note_top, null);
                holder.view = (EditText)convertView.findViewById(R.id.add_note_top_id);
                break;
            case TYPE_ITEM:
                convertView = inflater.inflate(R.layout.row_note, null);
                holder.view = (TextView)convertView.findViewById(R.id.note);
                getCursor().moveToPosition(position - 1);
                //              System.out.println("modified : " + getCursor().getInt(getCursor().getColumnIndex("_id")));
                ((TextView) holder.view).setText(getCursor().getInt(getCursor().getColumnIndex("_id")) + getCursor().getString(getCursor().getColumnIndex("content_note")));
                break;
            case TYPE_ADD_NOTE_BOTTOM:
                convertView = inflater.inflate(R.layout.add_note_bottom, null);
                holder.view = (EditText)convertView.findViewById(R.id.add_note_bottom_id);
                break;
            }
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder)convertView.getTag();
        }

        return convertView;
    }

    @Override
    public int getItemViewType(int position) {
        int type;
        if (position == addNoteTopPosition){
            type = TYPE_ADD_NOTE_TOP;
        } else if (position == addNoteBottomPosition){
            type = TYPE_ADD_NOTE_BOTTOM;
        }else {
            type = TYPE_ITEM;
        }
        return type;
    }

    @Override
    public int getViewTypeCount() {
        return TYPE_MAX_COUNT;
    }

    @Override
    public long getItemId(int position) {  
        return position;  
    }

    public static class ViewHolder {
        public View view;
    }

}

注意:我稍后会修复一些优化,如 viewHolder 等......

注意2:以防万一,这是我的主要活动代码

package com.android.activity;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewDebug.FlagToString;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.CursorAdapter;

import com.android.database.Note;
import com.android.database.NoteDataSource;

public class EverydayNotesAndroid3Activity extends Activity {
    /** Called when the activity is first created. */

    private Cursor cursorNotes;
    private NotesCursorAdapter notesCursorAdapter;
    private InputMethodManager imm;
    private Activity activity;
    private ListView listView;
    private int positionItem;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        activity = this;

        NoteDataSource.getSingletonObject(activity);

        NoteDataSource.getSingletonObject(activity).open();

        cursorNotes = NoteDataSource.getSingletonObject(activity).getCursorUpdatedDatabase(); // return all notes in a cursor

        startManagingCursor(cursorNotes);

        listView = (ListView) findViewById(R.id.main_list);

        notesCursorAdapter = new NotesCursorAdapter(activity, cursorNotes, 3);

        listView.setAdapter(notesCursorAdapter);

        Button b = new Button(activity);

        b = (Button) findViewById(R.id.done);

        b.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                NoteDataSource.getSingletonObject(activity).createNoteTop("Hello stack overflow world");
                cursorNotes = NoteDataSource.getSingletonObject(activity).getCursorUpdatedDatabase();
                notesCursorAdapter.changeCursor(cursorNotes); 
                notesCursorAdapter.notifyDataSetChanged();
            }

        });



        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id){
                if (position == 0){
                    showAlertWindowAddTop(parent, v, position, id);

                }else if (position == parent.getChildCount()-1){

                    showAlertWindowAddBottom(parent, v, position, id);
                }else{

                    showAlertWindowModify(parent, v, position, id);

                }

            }
        });

    }

不用担心:

1) 函数 showAlertWindowblabla() ==> 它有效

2) createNoteTop 函数也有效,它在数据库中插入一行。

感谢您的阅读,寻找您的答案。

编辑:好的,所以在做了一些 looooooong 的工作后,我越来越接近我想要的了。不幸的是我仍然有一个显示错误,当我修改一个字段时,我不知道为什么,他只是将该字段放在列表中的其他位置。我认为这是一个很容易修复的大错误(在 bindView 或 newView 方法上),但我很累,我找不到它的来源。因此,为了用一块石头杀死两只鸟,我发布了我的 customAdapter 的修改代码。

4

1 回答 1

1

子类很常见,CursorAdapter因为它意味着要这样做。如果您有简单的需求,您将使用ResourceCursorAdapter, 等。

所以只是一点背景:ListView回收视图。因此 newView 只被调用(屏幕上的项目数)+ 1(当你开始滚动时部分可见的那个)。然后这些项目在滚动到屏幕外时被重复使用。因此,在 newView 中设置文本标签几乎没有用,因为它无论如何都会在 bindView 中被覆盖(这是你应该这样做的地方),因为不会为每个 TYPE_ITEM 调用 newView。

所以我想主要问题是你正在通过修改newView方法中的 addNoteBottomPosition 来更改列表视图的内容,这是你能做的最糟糕的事情,真的。列表适配器旨在产生稳定的结果。这意味着如果你说那getItemViewType(8)是 TYPE_ADD_NOTE_BOTTOM 类型,你下次不能转身说“是的,现在是 TYPE_ITEM”。这就是你在做什么。newView您的代码依赖于按特定顺序调用的事实。另一个问题是你在搞乱CursorAdapter依赖的位置。

那么你如何解决这个问题呢?

有很多方法,我想你可能使用了更复杂的一种。最简单的方法是

aResourceCursorAdapter仅用于项目,ListView.addHeaderView()andListView.addFooterView()用于添加页眉和页脚。如果您查看 ListView 的源代码,那么您会注意到它addHeaderView实际上将使用HeaderViewListAdapter(http://developer.android.com/reference/android/widget/HeaderViewListAdapter.html),它基本上是一个包装器列表适配器,它环绕ListAdapter然后您将提供的嵌套。

使用这种方法,您无需担心不同的视图类型等。

如果我无法说服您并且您仍然想要子类化,CursorAdapter那么您需要查看它的实现。您会注意到它依赖于正确的位置,因此,如果您真的想弄乱位置并将它们与光标行位置分开,那么您将需要覆盖各种方法,例如getItem(), getItemId()

长话短说,你不想去那里。

于 2012-03-22T08:15:09.317 回答