我按照这个谷歌教程并实现了一个动态ListView进行拖放 https://www.youtube.com/watch?v=_BZIvjMgH-Q
listView = (DynamicListView) findViewById(R.id.listview);
adapter = new StableArrayAdapter(this, R.layout.text_view, arraylist);
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// added the items later and called notifyDataSetChanged();
arraylist.add("item 1");
arraylist.add("item 2");
arraylist.add("item 3");
arraylist.add("item 4");
adapter.notifyDataSetChanged();
它会显示列表视图中的所有项目,但是当我拖放元素时它们会消失。
如果我在设置适配器listView.setAdapter(adapter);
之前添加元素,它可以正常工作。
图书馆源代码http://developer.android.com/shareables/devbytes/ListViewDraggingAnimation.zip
我该如何解决这个问题?
更新
StableArrayAdapter.java
package com.example.android.navigationdrawerexample;
import android.content.Context;
import android.widget.ArrayAdapter;
import java.util.HashMap;
import java.util.List;
public class StableArrayAdapter extends ArrayAdapter<String> {
final int INVALID_ID = -1;
int mRowLayout;
List<String[]> mStrings;
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
// constructor
public StableArrayAdapter(Context context, int rowLayout, List<String> objects) {
super(context, rowLayout, objects);
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
@Override
public long getItemId(int position) {
if (position < 0 || position >= mIdMap.size()) {
return INVALID_ID;
}
String item = getItem(position);
return mIdMap.get(item);
}
@Override
public boolean hasStableIds() {
return true;
}
}
更新2 我按照建议在这里将项目添加到对象,它现在可以正常工作,但是在设置适配器之前是否与添加MainActivity中的项目相同?
public StableArrayAdapter(Context context, int rowLayout, List<String> objects) {
super(context, rowLayout, objects);
objects.add("item 1");
objects.add("item 2");
objects.add("item 3");
objects.add("item 4");
objects.add("item 5");
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
更新3 对象的大小仅在构造函数中是已知的 和 mIdMap.put(&#34; item 6&#34;,objects.size());在代码中没有效果。
// constructor
public StableArrayAdapter(Context context, int rowLayout, List<String> objects) {
super(context, rowLayout, objects);
this.objects = objects;
objects.add("item 1");
objects.add("item 2");
objects.add("item 3");
objects.add("item 4");
objects.add("item 5");
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
mIdMap.put("item 6", objects.size()); // has no effect
}
public void addItem(String item) {
int index = objects.size();
mIdMap.put(item, index);
}
答案 0 :(得分:1)
我通常会将项目添加到ArrayList中或修改适配器代码中的对象(在您的情况下为StableArrayAdapter),而不是像您所做的那样在适配器外部。但只要ArrayAdapter 之外的对象与StableArrayAdapter 中的列表共享相同的地址,这可能就没问题了。我怀疑它不是。
在您的情况下,请确保像arraylist.add("item 1")
这样的代码将字符串添加到StableArrayAdapter
中的ArrayList对象中。我再次怀疑它不是。
为了加快速度,请发布StableArrayAdapter
的代码。如果读者必须下载代码,读者就不方便提供帮助。
新建议代码:
在 StableArrayAdapter 中,添加一个公共方法,如:
// This method is opposite of getItemId().
public void addItem(String item) {
// Add the string into the objects
objects.add(item);
// size of objects should be added by one after add() above
int index = objects.size();
mIdMap.put(item, index);
}
在StableArrayAdapter之外:
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// added the item and called notifyDataSetChanged();
adapter.addItem("item 1");
adapter.addItem("item 2");
adapter.notifyDataSetChanged();
注意:不要在arraylist上添加项目,而是调用StableArrayAdapter,对象适配器的方法。
更新1 :问题是 DynamicListView 类中的方法setCheeseList
()和swapElements
()不适用于添加项目动态。此外, StableArrayAdapter 中的addItem
()也会更改。
我已经在我的项目中修复了这个问题,但这并不容易解释。所以我会尝试。
代码建议:
第1部分,FROM:
private void handleCellSwitch() {
...
swapElements(mCheeseList, originalItem, getPositionForView(switchView));
((BaseAdapter) getAdapter()).notifyDataSetChanged();
...
TO:
private void handleCellSwitch() {
...
// Swap the 2 items with animation for the dragNdrop feature
final SwappableListAdapter adapter = (SwappableListAdapter) getAdapter();
adapter.swap(originalItem, getPositionForView(switchView));
...
注意:
swapElements
()来交换mCheeseList之间的值,而是调用swap
类中实现的接口SwappableListAdapter
的方法StableArrayAdapter
()。 StableArrayAdapter
。 第2部分
接口代码SwappableListAdapter
:
public interface SwappableListAdapter {
/**
* Swaps between 2 items in the adapter, one is the mobile item, another is the selected item.
* Method notifyDataSetChanged is called in the swap() when finished.
* @param index1 The selected row view, dragged and to be moved.
* @param index2 The row which moved due to the dragged row item.
*/
public void swap(int index1, int index2);
}
注意:
第3部分
在swap
类中实现StableArrayAdapter
()方法的代码。
以强>
public class StableArrayAdapter extends ArrayAdapter<String> implements DynamicListView.SwappableListAdapter {
...
@Override
public void swap(int indexOne, int indexTwo) {
// Swap mIdMap object related to indexOne and indexTwo
String item = getItem(indexOne);
notifyDataSetChanged();
}
注意:
swap
()需要工作。我的项目不使用 HashMap 进行交换,我不喜欢HashMap的当前实现(来自Google工程师)。我可能有时间修理它。也许你可以修复这个方法。希望你现在有了这个想法。StableArrayAdapter
类现在实现了接口SwappableListAdapter
,并且有权覆盖swap()。答案 1 :(得分:1)
Thanx一吨到@The Original Android
动态添加项目时所做的更改摘要。
StableArrayAdapter.java
添加了addItem方法
public void addItem(String item) {
// Add the string into the objects
objects.add(item);
// size of objects should be added by one after add() above
int index = objects.size();
mIdMap.put(item, index);
}
<强> MainActivity.java 强>
listView.setCheeseList(al);
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// called addItem method inside MainActivity
adapter.addItem("item 1");
adapter.addItem("item 2");
adapter.addItem("item 3");
adapter.addItem("item 4");
adapter.notifyDataSetChanged();
<强> DynamicListView.java 强>
从
更改 private void handleCellSwitch() {
...
swapElements(mCheeseList, originalItem, getPositionForView(switchView));
((BaseAdapter) getAdapter()).notifyDataSetChanged();
...
}
到
private void handleCellSwitch() {
...
final SwappableListAdapter adapter = (SwappableListAdapter) getAdapter();
adapter.swap(mCheeseList,originalItem, getPositionForView(switchView)); // I still had to pass the arraylist
...
}
在DynamicListView.java中创建了一个接口
public interface SwappableListAdapter {
public void swap(int index1, int index2);
}
StableArrayAdapter.java实现SwappableListAdapter接口并覆盖交换方法
public class StableArrayAdapter extends ArrayAdapter<String> implements DynamicListView.SwappableListAdapter {
@Override
public void swap(ArrayList a,int index1, int index2) {
Object temp = a.get(index1);
a.set(index1, a.get(index2));
a.set(index2, temp);
notifyDataSetChanged();
}
}
答案 2 :(得分:1)
这可能不是完全相同的问题,但它很相似,而且谷歌带领我来到这里。我的列表视图主要是有效的,但是有一系列动作可以使某些项目消失。之后单击它们会导致NullPointerException。
以下是重现错误的步骤:
调试后,我发现我的StableArrayAdapter.getView()方法被调用了两次,仅用于列表顶部的空白项。这让我想到了这个问题Adapter getView is called multiple times with position 0 提到了一个动态的全高度&#34;。
为了解决这个问题,我将DynamicListView的layout_height设置为&#34; wrap_content&#34;。