我开始了一个小型的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
答案 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