如何在Drag-Sort ListView中刷新ListView?

4
我已经在我的项目中同时使用了Drag-Sort ListView(DSLV)和LazyList,我从github上下载了LazyListDrag-Sort ListView的演示文件,然后根据我的要求进行集成和修改。
我使用DSLV来拖动和排序ListView中的项目,并使用LazyList来显示来自URL的图像。我只是实现了DSLV的“基本用法游乐场”来进行拖放排序。
我已经在TestBedDSLV.java中实现了搜索,但问题是当我从列表中搜索内容时,无法更新列表。我尝试过notifyDataSetChanged方法,但它没有起作用。通常我们会创建新的适配器并将其传递给listview,例如lv.setAdapter(adapter),但这里他们只设置了ListAdapter,所以我们不能做lv.setAdapter(adapter)。

TestBedDSLV.java

package com.mobeta.android.demodslv;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.MenuInflater;
import android.widget.Button;
import android.widget.EditText;

import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;

public class TestBedDSLV extends FragmentActivity { 

private int mNumHeaders = 0;
private int mNumFooters = 0;

private int mDragStartMode = DragSortController.ON_DOWN;
private boolean mRemoveEnabled = false;
private int mRemoveMode = DragSortController.FLING_RIGHT_REMOVE;
private boolean mSortEnabled = true;
private boolean mDragEnabled = true;

private String mTag = "dslvTag";
Button search;
EditText search_customer;

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

    search = (Button) findViewById(R.id.btn_search);
    search_customer = (EditText) findViewById(R.id.search_product);

    search_customer.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before,
                int count) {

            // here is logic for refresh the list View
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {

        }

        @Override
        public void afterTextChanged(Editable s) {

        }
    });

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.test_bed, getNewDslvFragment(), mTag).commit();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.mode_menu, menu);
    return true;
}


private Fragment getNewDslvFragment() {
    DSLVFragmentClicks f = DSLVFragmentClicks.newInstance(mNumHeaders,
            mNumFooters);
    f.removeMode = mRemoveMode;
    f.removeEnabled = mRemoveEnabled;
    f.dragStartMode = mDragStartMode;
    f.sortEnabled = mSortEnabled;
    f.dragEnabled = mDragEnabled;
    return f;
}
}

DSLVFragmentClicks.java

package com.mobeta.android.demodslv;

import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.os.Bundle;
import android.widget.Toast;

public class DSLVFragmentClicks extends DSLVFragment {

public static DSLVFragmentClicks newInstance(int headers, int footers) {
    DSLVFragmentClicks f = new DSLVFragmentClicks();

    Bundle args = new Bundle();
    args.putInt("headers", headers);
    args.putInt("footers", footers);
    f.setArguments(args);

    return f;
}

AdapterView.OnItemLongClickListener mLongClickListener = 
        new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                String message = String.format("Long-clicked item %d", arg2);
                Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
                return true;
            }
        };

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

    ListView lv = getListView();
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            String message = String.format("Clicked item %d", arg2);
            Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();

        }
    });
    lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            String message = String.format("Long-clicked item %d", arg2);
            Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
            return true;
        }
    });
}
}

DSLVFragment.java

package com.mobeta.android.demodslv;

import java.util.ArrayList;
import java.util.Arrays;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

import com.mobeta.android.dslv.DragSortController;
import com.mobeta.android.dslv.DragSortListView;

public class DSLVFragment extends ListFragment {

ArrayAdapter<String> adapter;

private String[] array;
public static ArrayList<String> list;

private DragSortListView.DropListener onDrop = new DragSortListView.DropListener() {
    @Override
    public void drop(int from, int to) {
        if (from != to) {
            String item = adapter.getItem(from);
            adapter.remove(item);
            adapter.insert(item, to);
        }
    }
};

private DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener() {
    @Override
    public void remove(int which) {
        adapter.remove(adapter.getItem(which));
    }
};

protected int getLayout() {
    return R.layout.dslv_fragment_main;
}

/**
 * Return list item layout resource passed to the ArrayAdapter.
 */
protected int getItemLayout() {
    return R.layout.list_item_handle_right;

}

private DragSortListView mDslv;
private DragSortController mController;

public int dragStartMode = DragSortController.ON_DOWN;
public boolean removeEnabled = false;
public int removeMode = DragSortController.FLING_RIGHT_REMOVE;
public boolean sortEnabled = true;
public boolean dragEnabled = true;

public static DSLVFragment newInstance(int headers, int footers) {
    DSLVFragment f = new DSLVFragment();

    Bundle args = new Bundle();
    args.putInt("headers", headers);
    args.putInt("footers", footers);
    f.setArguments(args);

    return f;
}

public DragSortController getController() {
    return mController;
}

/**
 * Called from DSLVFragment.onActivityCreated(). Override to set a different
 * adapter.
 */
public void setListAdapter() {
    array = getResources().getStringArray(R.array.jazz_artist_names);
    list = new ArrayList<String>(Arrays.asList(array));

    adapter = new ArrayAdapter<String>(getActivity(), getItemLayout(),
            R.id.text, list);
    setListAdapter(adapter);
}

/**
 * Called in onCreateView. Override this to provide a custom
 * DragSortController.
 */
public DragSortController buildController(DragSortListView dslv) {
    DragSortController controller = new DragSortController(dslv);
    controller.setDragHandleId(R.id.drag_handle);
    controller.setClickRemoveId(R.id.click_remove);
    controller.setRemoveEnabled(removeEnabled);
    controller.setSortEnabled(sortEnabled);
    controller.setDragInitMode(dragStartMode);
    controller.setRemoveMode(removeMode);
    return controller;
}

/** Called when the activity is first created. */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    mDslv = (DragSortListView) inflater.inflate(getLayout(), container,
            false);

    mController = buildController(mDslv);
    mDslv.setFloatViewManager(mController);
    mDslv.setOnTouchListener(mController);
    mDslv.setDragEnabled(dragEnabled);

    return mDslv;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    mDslv = (DragSortListView) getListView();

    mDslv.setDropListener(onDrop);
    mDslv.setRemoveListener(onRemove);

    Bundle args = getArguments();
    int headers = 0;
    int footers = 0;
    if (args != null) {
        headers = args.getInt("headers", 0);
        footers = args.getInt("footers", 0);
    }
    setListAdapter();
}
}

test_bed_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<LinearLayout
    android:id="@+id/search_lay"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:orientation="horizontal" >

    <EditText
        android:id="@+id/search_product"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="2dp"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="2dp"
        android:layout_weight="1"
        android:background="@drawable/search_back"
        android:hint="Enter Firstname"
        android:imeOptions="actionSearch"
        android:inputType="text"
        android:paddingBottom="2dp"
        android:paddingLeft="5dp"
        android:paddingTop="2dp"
        android:visibility="visible" />

    <Button
        android:id="@+id/btn_search"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_weight="2.5"
        android:text="CANCEL"
        android:textColor="#155280"
        android:textSize="14sp"
        android:textStyle="bold"
        android:visibility="visible" />
</LinearLayout>

<FrameLayout
    android:id="@+id/test_bed"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
<!-- We will add the DSLVFragment inside the FrameLayout in code -->

</LinearLayout>

enter image description here

其他所需的类可以从我提供的Github链接下载...


2
你粘贴了太多的代码。为什么不试着缩小范围,只保留重要的行呢? - asloob
"说话容易,做出代码来才是硬道理。" - JJ86
我已经发布了代码,请检查一下。 - Jayesh
有时候如果你没有初始化ArrayList,它会生成空指针异常。你应该先初始化ArrayList。 - TheLittleNaruto
2个回答

1
实际上,如果您仔细查看您的代码,您会发现有一个您提到的方法。
public void setListAdapter() {
    array = getResources().getStringArray(R.array.jazz_artist_names);
    list = new ArrayList<String>(Arrays.asList(array));

    adapter = new ArrayAdapter<String>(getActivity(), getItemLayout(),
            R.id.text, list);
    setListAdapter(adapter);
}

所以你的意思是:

"通常我们创建新适配器并将其传递给ListView,例如lv.setAdapter(adapter),但是这里只设置了ListAdapter,所以我们不能做lv.setAdapter(adapter)"

你不能通过轻松生成基于搜索的数组并像代码一样设置它来轻松完成此操作吗?

list = new ArrayList<String>(Arrays.asList(array));

        adapter = new ArrayAdapter<String>(getActivity(), getItemLayout(),
                R.id.text, list);
        setListAdapter(adapter);

编辑:我认为你提出了错误的问题。你的主要关注点应该是如何在活动和片段之间进行通信...因为你的搜索功能在活动中,而列表在片段中。所以你需要设置一个接口,基本上将搜索字符串传递到你的片段中,在那里你可以创建一个数组,并像现在一样设置它。

阅读thisSO问题和答案。在答案中,你会发现一种类似的通过活动和片段之间传递数据的方法。

编辑2:你的主要问题是为了用于从活动到片段的通信..在你的活动中声明一个接口,就像这样:

    public interface FragmentCommunicator{
       public void passDataToFragment(String someValue);
    }

then call the interface at your text change listener..for example

    FragmentCommunicator mfragmentCommunicator;
    //your onCreate function 
    {
    //your textchangelistenr
    {
    onTextChanged call 
if(mfragmentCommunicator != null)
   mfragmentCommunicator.passDataToFragment(Pass your string here)
    }

then make your fragement implement this interface like

public class someFragment extends Fragment implements FragmentCommunicator
{
//this is your rest of the fragment

@Override
public void passDataToFragment(String somevalue)
{
//This function will get fired each time your text is changed since in your activity you are calling this same function in your textchange listener. the String somevalue will be the string that you passed from your activity


}

//rest of the code
.
.
.
//Don't forget to initialize your interface in fragment itself. Do this in your onAttach
like this
@Override
 public void onAttach(Activity activity){
  super.onAttach(activity);
  context = getActivity();

  ((MainActivity)context).fragmentCommunicator = this;
}

}

}

您可以参考 此链接 以获取更多澄清。仅检查FragmentCommunicator的实现。


我已经尝试了很多次,但它无法工作.....请告诉我从哪里设置?我已经在TestBedDSLV.java文件中实现了搜索功能,并且我必须从TestBedDSLV.java进行设置,我已经尝试了很多次,但它无法工作....我认为这个setListAdapter只能在DSLV中设置一次。 - Jayesh
setListAdapter只是因为该类扩展了ListFragment而存在。如果您将其扩展到fragment,则可以使用setadapter。没有区别。无论如何,您始终可以在活动和片段之间创建接口,以便直接在片段本身中刷新视图。 - Parvaz Bhaskar
我刚刚看到了那个 Stack Overflow 的问题,当调用 getData() 方法时,只有在活动启动时才会调用吗??当我进行搜索时,如何发送数据?? - Jayesh
你只有一个片段还是要添加多个? - Parvaz Bhaskar
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/28427/discussion-between-jayesh-and-parvaz-bhaskar - Jayesh
显示剩余7条评论

1
如果您将数组用作适配器的基本arraylist,请更新此数组并调用adapater.notifyDataSetChanged()。这样做肯定会更新DSLV,因为我在我的一个项目中使用了相同的方法。

我已经尝试了很多次,但对我来说没有用...这不是一个小问题... - Jayesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接