我刚刚实现了此滑动删除solution。
我从Rails API(我自己的)中显示ListView中的数据,并使用滑动从ListView中删除项目,并进行网络调用从数据库中删除项目。我将listview中每个项目的ID放在隐藏的TextView
中,并在发送请求时拉出该ID,以便服务器端知道要删除的项目:
// all in onCreate()
SwipeDismissListViewTouchListener touchListener =
new SwipeDismissListViewTouchListener(
listView,
new SwipeDismissListViewTouchListener.DismissCallbacks() {
@Override
public boolean canDismiss(int position) {
return true;
}
@Override
public void onDismiss(ListView listView, int[] reverseSortedPositions) {
for (int position : reverseSortedPositions) {
TextView listItemId = (TextView) findViewById(R.id.list_item_id);
String deleteId = listItemId.getText().toString();
//volley delete call
deleteListItem(deleteId);
shoppingListItems.remove(listAdapter.getItem(position));
}
listAdapter.notifyDataSetChanged();
}
});
listView.setOnTouchListener(touchListener);
以下是截击:
public void deleteListItem(String item_id) {
String deleteUrl = "http://polar-beach-6028.herokuapp.com/api/v1/list_items/" + item_id;
JsonObjectRequest deleteRequest = new JsonObjectRequest(Request.Method.DELETE, deleteUrl, null,
new Response.Listener<JSONObject>() {
@Override public void onResponse(JSONObject response) {
try {
if (response.getBoolean("success")) {
Toast.makeText(getApplicationContext(), "List item deleted.", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.d("Error.Response", e.toString());
Toast.makeText(getApplicationContext(), "Could not delete list item.", Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
@Override public void onErrorResponse(VolleyError error) {
Log.d("Error.response", error.toString());
Toast.makeText(getApplicationContext(), "Could not delete list item.", Toast.LENGTH_LONG).show();
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("auth_token", mPreferences.getString("AuthToken", "") );
return headers;
}
};
AppController.getInstance().addToRequestQueue(deleteRequest);
}
列表视图中项目的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/feed_bg"
android:orientation="vertical" >
<TextView
android:id="@+id/list_item_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="@dimen/feed_item_margin"
android:layout_marginRight="@dimen/feed_item_margin"
android:layout_marginTop="@dimen/feed_item_margin"
android:background="@drawable/bg_parent_rounded_corner"
android:orientation="vertical"
android:paddingBottom="@dimen/feed_item_padding_top_bottom"
android:paddingTop="@dimen/feed_item_padding_top_bottom" >
<TextView
android:id="@+id/product"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingLeft="@dimen/feed_item_status_pad_left_right"
android:paddingRight="@dimen/feed_item_status_pad_left_right"
android:paddingTop="@dimen/feed_item_status_pad_top" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="@dimen/feed_item_padding_left_right"
android:paddingRight="@dimen/feed_item_padding_left_right" >
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/itemImg"
android:layout_width="@dimen/feed_item_vendor_pic_width"
android:layout_height="@dimen/feed_item_vendor_pic_height"
android:scaleType="fitCenter" >
</com.android.volley.toolbox.NetworkImageView>
</LinearLayout>
<TextView
android:id="@+id/store_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingLeft="@dimen/feed_item_status_pad_left_right"
android:paddingRight="@dimen/feed_item_status_pad_left_right"
android:paddingTop="@dimen/feed_item_status_pad_top" />
</LinearLayout>
</LinearLayout>
它在第一次删除时效果很好,但是在数据集更改后,网络调用(使用Volley)开始发送错误listItemId
的请求。结果是错误的列表项被删除,并且当列表被删除时,我最终在服务器端出现错误,因为Volley正在发送已经被错误删除的项的删除请求。我不确定为什么会这样,有什么帮助吗?如果它有帮助,我很乐意发布其他代码,但为了简洁,我会将其留在此处。
更新
这是我的父xml布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#ffffff">
<ListView
android:id="@+id/shopping_list_show"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:dividerHeight="1dp"
android:cacheColorHint="#00000000"/>
</LinearLayout>
答案 0 :(得分:2)
以下电话可能是罪魁祸首:
TextView listItemId = (TextView) findViewById(R.id.list_item_id);
如果没有指定应该查找R.id.list_item_id
的位置,您可以尝试在活动的布局中找到它 - 而不是在listview项目的布局中找到它。
根据您的描述,执行时您应该面对NullPointerException
:
String deleteId = listItemId.getText().toString();
但是,由于您没有报告NPE,我怀疑您的活动布局中有一个ID为R.id.list_item_id
的TextView。
您需要访问“走了多少”&#39; textview(保持项目ID)是列表项视图。因此,让我们尝试定制您从中获得的代码 - here。
您正在使用的回调接口是:
public interface DismissCallbacks {
// Called to determine whether the given position can be dismissed.
boolean canDismiss(int position);
// Called when the user has indicated they she would like to dismiss
// one or more list item positions.
void onDismiss(ListView listView, int[] reverseSortedPositions);
}
正如您所看到的,它并不能为您提供所需的一切。让我们解决此问题以返回所有相关信息。编辑将进入SwipeDismissListViewTouchListener.java
(第104行):
public interface DismissCallbacks {
// Called to determine whether the given position can be dismissed.
boolean canDismiss(int position);
// Called when the user has indicated they she would like to dismiss
// one or more list item positions.
// Item ids are also returned.
void onDismiss(ListView listView, int[] reverseSortedPositions, String[] itemIds);
}
PendingDismissData
包含要解除的列表项的View
和列表position
。我们可以像这样提取item id
:
修改performDismiss(View, int)
中的方法SwipeDismissListViewTouchListener
:
public void onAnimationEnd(Animator animation) {
--mDismissAnimationRefCount;
if (mDismissAnimationRefCount == 0) {
// No active animations, process all pending dismisses.
// Sort by descending position
Collections.sort(mPendingDismisses);
int[] dismissPositions = new int[mPendingDismisses.size()];
---->>> String[] itemIds = new String[mPendingDismisses.size()];
for (int i = mPendingDismisses.size() - 1; i >= 0; i--) {
dismissPositions[i] = mPendingDismisses.get(i).position;
// The view that holds the textview
View dView = mPendingDismisses.get(i).view;
// Find the textview in `dView`
TextView listItemId = (TextView) dView.findViewById(R.id.list_item_id);
// Add id to the array
---->>> itemIds[i] = listItemId.getText().toString();
}
// Include the ids in the callback
mCallbacks.onDismiss(mListView, dismissPositions, itemIds);
......
......
您的实施也会发生变化:
@Override
public void onDismiss(ListView listView, int[] reverseSortedPositions, String[] itemIds) {
for (int i = 0; i < reverseSortedPositions.length; i++) {
//volley delete call
deleteListItem(itemIds[i]);
shoppingListItems.remove(listAdapter.getItem(reverseSortedPositions[i]));
}
listAdapter.notifyDataSetChanged();
}
如果这仍然无法解决您的问题,请发布您的适配器代码。您如何为隐藏的textview分配/更新值可能存在问题。
注意:最好以另一种方式包含项目ID - 这并不需要您使用额外的textview。也许,您可以将商品ID设置为convertView
的标签,并在SwipeDismissListViewTouchListener
中访问它?