如何使用CursorAdapter从ListView中删除行

时间:2015-01-31 17:27:56

标签: android listview android-cursoradapter activeandroid

我开始了一个小型的Android项目来重新学习一些Android开发,我已经卡住了......

我不知道如何实现删除ListView元素的删除!

以下是项目:https://github.com/gdurelle/Listify

现在它的目的是展示元素列表。

我使用自定义CursorAdapter来显示我的元素列表,并且我已经有一个(丑陋)破坏按钮,但我不知道如何使它从列表中删除一个实际元素(和数据库) )。

我使用 ActiveAndroid ActiveRecord 的方式管理数据库。

另外:我不确定是否使用getView()bindView()和/或newView() ......

我创建了一个问题来记住这一点,并在此处引用此问题:https://github.com/gdurelle/Listify/issues/1

public class ListifyCursorAdapter extends CursorAdapter {
  public String content;
  public ListifyCursorAdapter(Context context, Cursor cursor) {
    super(context, cursor, 0);
  }
  // The newView method is used to inflate a new view and return it, you don't bind any data to the view at this point.
  @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
      return LayoutInflater.from(context).inflate(R.layout.element_line, parent, false);
    }
  // The bindView method is used to bind all data to a given view such as setting the text on a TextView.
  @Override
  public void bindView(View view, Context context, Cursor cursor) {
  // Find fields to populate in inflated template
    TextView tvBody = (TextView) view.findViewById(R.id.element_content);
    // Extract properties from cursor
    content = cursor.getString(cursor.getColumnIndexOrThrow("content"));
    // Populate fields with extracted properties
    tvBody.setText(content);
  }
}

在我的MainActivity中:

 Cursor cursor = ListifyElement.fetchResultCursor();
 adapter = new ListifyCursorAdapter(this, cursor);
 listView.setAdapter(adapter);

我想的可能是:

Button delete_button = (Button) listView.findViewById(R.id.delete_button);

类似于ListifyElement.load(ListifyElement.class, the_id_of_the_element).delete();,其中 the_id_of_the_element 将是从UI点击它的delete_button以某种方式检索到的元素的数据库ID ...

更新

@Override
public void bindView(View view, Context context, final Cursor cursor) {
    // Find fields to populate in inflated template
    TextView tvBody = (TextView) view.findViewById(R.id.element_content);
    // Extract properties from cursor
    content = cursor.getString(cursor.getColumnIndexOrThrow("content"));
    // Populate fields with extracted properties
    tvBody.setText(content);

    Button delete_button = (Button) view.findViewById(R.id.delete_button);
    delete_button.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            System.out.println(cursor.getColumnName(0)); // Id
            System.out.println(cursor.getColumnName(1)); // ListifyContainer
            System.out.println(cursor.getColumnName(2)); // content
            System.out.println(cursor.getColumnIndexOrThrow("Id")); // 0
            ListifyElement.load(ListifyElement.class, cursor.getColumnIndexOrThrow("Id")).delete();
            notifyDataSetChanged();
        }
    });

单击删除按钮时出现此错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.gdurelle.listify.models.ListifyElement.delete()' on a null object reference

5 个答案:

答案 0 :(得分:0)

如果您希望每行Button,则应将其添加到xml中的newView()。之后,您应该将OnClickListener设置为Button内的bindView()。这样的事情:

public void bindView(View view, Context context, Cursor cursor) {
 // Find fields to populate in inflated template
TextView tvBody = (TextView) view.findViewById(R.id.element_content);
Button delete_button = (Button) view.findViewById(R.id.delete_button);
delete_button.setOnClickListener(new OnClickListener(){
     @Override
     public void onClick(View v){
       //As you're using ActiveAndroid
       new Delete().from(ListfyElement.class).where("yourCondition=?",yourCondition).execute();
       notifyDataSetChanged();

     } 
});
// Extract properties from cursor
content = cursor.getString(cursor.getColumnIndexOrThrow("content"));
// Populate fields with extracted properties
tvBody.setText(content);

}

答案 1 :(得分:0)

使用以下代码执行此操作 -

ListView lv;
ArrayList<String> arr = new ArrayList<String>();
ArrayAdapter adapter;
int position;

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.extra);

    for(int i=0;i<5;i++)arr.add("Hi @ "+i);

    lv = (ListView) findViewById(R.id.listViewBirthday);
    lv.setOnItemLongClickListener(this);
    adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, arr);
    lv.setAdapter(adapter);
}

@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
    // TODO Auto-generated method stub
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuItem it1=menu.add("Delete");
}

@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int p, long arg3) 
{
    position = p;
    registerForContextMenu(lv);
    return false;
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    if(item.getTitle().equals("Delete"))
    {
        arr.remove(position);
        adapter.notifyDataSetChanged();
        Toast.makeText(getBaseContext(), "deleted", Toast.LENGTH_SHORT).show();
    }
    return true;
}

答案 2 :(得分:0)

在列表视图上实现上下文菜单相对简单。它(上下文菜单)在长按该项目时激活。我的建议是为菜单项添加一个intent,这样你就可以保留自定义适配器中的item id并使用它来执行你想要的任何内容。

public class MainActionBarTabListFragment extends ListFragment {

@Override
public void onActivityCreated(Bundle savedState) {
    super.onActivityCreated(savedState);
    registerForContextMenu(getListView());
}


@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {

    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        String name = adapter2.getItem(info.position).get_name();
        menu.setHeaderTitle(name);
        MenuInflater inflater = this.getActivity().getMenuInflater();
        inflater.inflate(R.menu.menulistitem, menu);
        MenuItem mi = menu.findItem(R.id.action_context_delete);
        Intent i = new Intent();
        i.putExtra("id", adapter2.getItem(info.position).get_id());
        mi.setIntent(i);
    }
}

@Override
public boolean onContextItemSelected(MenuItem item) {

    switch (item.getItemId()) {
    case R.id.action_context_delete:
        Intent i = item.getIntent();
        if (i != null) {
            Bundle b = i.getExtras();
            if (b != null) {
                int id = b.getInt("id");
                Uri deleteIdUri = ContentUris.withAppendedId(
                        RidesDatabaseProvider.CONTENT_URI, id);
                context.getContentResolver()
                        .delete(deleteIdUri, null, null);
                return true;
            }
        }
    }
    return super.onContextItemSelected(item);
}

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:yourapp="http://schemas.android.com/apk/res-auto" >

    <item
        android:id="@+id/action_context_delete"
        android:icon="@drawable/action_about"
        android:orderInCategory="100"
        android:showAsAction="ifRoom"
        android:title="delete"
        yourapp:showAsAction="ifRoom"/>

</menu>

答案 3 :(得分:0)

让我们从头开始,你为什么需要使用ActiveAndroid?我建议避免这样的事情,恕我直言。你混合了你的逻辑,适配器不应该改变你的数据库。将侦听器设置为适配器(即IDeleteListener使用单个方法onDeleteRequested(long rowId))。接下来,您需要传递rowId,例如:

delete_button.setTag(cursor.getLong(0));
delete_button.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            listener.onDeleteRequested((Long)v.getTag());
        }
    });

在您的片段/活动类中,您应该设置一个适配器的监听器并使用您的数据库。我建议你使用LoaderManager这将自动重新查询你的数据删除和处理活动的生命周期。 希望有所帮助!

答案 4 :(得分:0)

我建议您改用ArrayAdapter。然后,您只是使用ArrayList(或任何其他数组)进行编辑,然后致电adapter.notifyDataSetChanged();ListView的内容将会更新。

像这样声明ArrayAdapter

ArrayAdapter<String> adapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_list_item_1, yourStringArray);

其中名为yourStringArray的变量只是ArrayList的{​​{1}}。

然后,将适配器添加到String,如下所示:

ListView

然后,您可以通过编辑yourListView.setAdapter(adapter); 列表并调用yourStringArray来修改列表的内容。这是一个简单的例子:

adapter.notifyDataSetChanged();

最后,要在单击按钮时删除所选项目,您可以执行以下操作:

list.add("Hello!");
adapter.notifyDataSetChanged();

整个int selectedItemIndex = 0; yourArrayList.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectedItemIndex = position; } }); yourDestroyButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { yourStringArray.remove(selectedItemIndex); adapter.notifyDataSetChanged(); } }); 方法看起来像这样:

onCreate