最近一段时间准备写一个具有左滑删除,长按排序等功能的listview,后来发现小白根本写不出来这种东西,于是在GitHub中知道了一个开源项目——drag_sort_listview。
这个项目看网上很多人用,但是这个项目自从2013年就没有更新过了,而网上很多版本的教程也并不是13年最后更新的教程,所以我结合网上的教程和自己摸索,写了这篇文章。这里使用的是AS 不是eclipse
原项目地址: bauerca/drag-sort-listview
首先第一步就是下载这个项目到电脑,这个不用教
然后下载好了以后找到library文件夹,我给他改了个名字,反正没差,我这里叫做
然后准备导入as
点击菜单栏 File→New→import Moudle 然后找到对应的你的这个 library文件夹,然后导入
导入之后会报错,adk啊,gradle啊 版本都不一样,所以需要下载 adk 并修改dragsortlistview的build.gradle文件。
具体怎么修改,可以百度一下 如何导入guthub项目到AS
修改好以后,添加依赖(我一开始没添加依赖也可以用...不知道为啥)
就可以开始写 我们的新listview了 此时,你有两个文件目录,一个是你主程序的,一个是你的library的。第一步在你的主界面布局中使用dragsortlistview。
新建一个布局。我的布局如下
<?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:orientation="vertical" android:gravity="center"> <com.mobeta.android.dslv.DragSortListView xmlns:dslv="http://schemas.android.com/com.mobeta.android.dslv" android:id="@+id/dslvList" android:layout_width="match_parent" android:layout_height="0dp" android:layout_margin="3dp" android:layout_weight="1.0" android:divider="@null" dslv:collapsed_height="1px" dslv:drag_scroll_start="0.3" dslv:float_alpha="1.0" dslv:slide_shuffle_speed="0.7" dslv:drop_animation_duration="150" dslv:remove_animation_duration="150" dslv:track_drag_sort="false" dslv:use_default_controller="true" dslv:sort_enabled="true" dslv:drag_start_mode="onLongPress" dslv:remove_enabled="false" dslv:remove_mode="flingRemove" dslv:fling_handle_id="@id/tv_content" dslv:float_background_color="@color/BLACK" dslv:drag_handle_id="@id/drag_handle" />
给大家解释一下各行的意思
第一行是解释这个view的地址,因为是导入的library里的,所以需要加上这个。这个地址可以在library的文件夹上找到
、
后面是listview这个view的基础属性
再后面则是dragsortlistview的属性了,dragsortlistview的属性有很多,我原来在这就是被网上的其他教程坑了一把,因为后来项目的所有者对项目有所修改,所以属性也有变化。
项目的xml属性有很多,在以下列出,一下内容机翻自原项目网址,可能有点不通顺,大致意思理解就可以了。
-
collapsed_height
:(尺寸,1px)原始拖动位置处的占位符高度。不能为零。 -
drag_scroll_start
:(float,0.3)拖动滚动区域的开始(由总DSLV高度的一部分定义;即在0和1之间)。 -
max_drag_scroll_speed
:(float,0.5)默认线性拖动滚动配置文件的最大拖动滚动速度。像素单位/毫秒。 -
float_alpha
:(float,1.0)浮动视图的透明度。值从0到1,其中1不透明。 -
slide_shuffle_speed
:(浮点数,0.7)浮动视图下的随机动画的速度。值为0意味着一个随机动画总是在进行中,而值为1意味着项目在没有动画的情况下从一个位置捕捉到另一个位置。 -
drop_animation_duration
:(int,150)在销毁动画之前,将动画顺畅放置在放置槽中心。持续时间以毫秒为单位。 -
remove_animation_duration
:(int,150)删除一个项目时平滑移除动画会折叠空的插槽。持续时间以毫秒为单位。 -
track_drag_sort
:(布尔,错误)调试选项; 下面解释。 -
use_default_controller
:(bool,true)让DSLV创建DragSortController实例并将下列xml属性传递给它。如果将其设置为false,请忽略以下属性。 -
float_background_color
:(color,BLACK)使用默认的DragSortController设置浮动视图的背景颜色。在这种情况下浮动视图是要拖动的列表项的快照。 -
drag_handle_id
:(id,0)指向子项的Android资源ID查看列表项(或列表项布局的根视图)。这标识了“拖动手柄”,或列表项中必须触摸的视图,以开始对该项目进行拖动分类。如果要使用默认DragSortController启用拖动,则为必需。 -
sort_enabled
:(bool,true)启用拖拽项目的排序(禁用在仅需要删除项目时非常有用)。 -
drag_start_mode
:(枚举,“onDown”)设置开始拖动的手势。- “onDown”:当手指触摸拖动手柄时,拖动开始。
- “onDrag”:拖动开始时,手指触摸拖动手柄,然后拖动(允许项目点击和长时间点击)。
- “onLongPress”:拖动开始拖动手柄长按(允许项目点击)。
-
remove_enabled
:(bool,false)通过remove_mode
以下选项之一启用拖动项目删除。 -
remove_mode
:(enum,“flingRight”)设置用于移除拖动项目的手势。-
“clickRemove”:点击具有ID的项目子视图
click_remove_id
。 - “flingRemove”:在物品上的任何位置水平投掷。
-
“clickRemove”:点击具有ID的项目子视图
-
click_remove_id
:(id,0)Android资源ID,指向一个列表项的子视图。当remove_mode="clickRemove"
和remove_enabled="true"
,点击这个子View查看包含的项目。这个attr被DragSortController使用。 -
fling_handle_id
:(id,0)Android资源ID,指向一个列表项的子视图。当remove_mode="flingRemove"
和remove_enabled="true"
,源自这个子View的一个fling删除了包含的项目。这个attr被DragSortController使用。
在网上其他介绍中有很多已经被修改了,还有的修改了并没有写在上面的属性。下面列出
1.作者对删除item的手势操作从3个简化到两个,即将左滑右滑合并为一个 fling。即remove_mode="flingRemove"
2.作者在attr里面将拖拽的onDrag模式改成onMove模式,这里需要注意
3.handle_id和remove_id,这两个id需要@一个id名,这个id名需要引用你listview的item布局中的一个view的id。因为两个代码不在同一个布局文件中,所以需要在values中创建ids文件。然后放id进去,在item中直接引用
这样就会报错了!
接下来就是写 自己的适配器了,因为他原项目不知道你是怎么处理数据的,所以这里要自己写适配器
我的适配器代码如下:
class MyAdapter extends BaseAdapter { private List<Event> mList;//数据源 private LayoutInflater mInflater;//布局装载器对象 // 通过构造方法将数据源与数据适配器关联起来 // context:要使用当前的Adapter的界面对象 MyAdapter(Context context, List<Event> list) { mList = list; mInflater = LayoutInflater.from(context); } @Override //ListView需要显示的数据数量 public int getCount() { return mList.size(); } @Override //指定的索引对应的数据项 public Object getItem(int position) { return mList.get(position); } @Override //指定的索引对应的数据项ID public long getItemId(int position) { return position; } @Override //返回每一项的显示内容 public View getView(int position, View convertView, ViewGroup parent) {//如果view未被实例化过,缓存池中没有对应的缓存 if (convertView == null) { convertView = mInflater.inflate(R.layout.item, null); } /* * 找到item布局文件中对应的控件 */ TextView contentTextView = (TextView) convertView.findViewById(R.id.tv_content); //获取相应索引的ItemBean对象 Event event = mList.get(position); /* * 设置控件的对应属性值 */ contentTextView.setText(event.getContent()); return convertView; } void remove(int arg0) {//删除指定位置的item mList.remove(arg0); this.notifyDataSetChanged();//不要忘记更改适配器对象的数据源 } void insert(Event item, int arg0) {//在指定位置插入item mList.add(arg0, item); this.notifyDataSetChanged(); } }
只需要注意,比一般重写适配器多两个方法,remove和insert方法
这里还涉及到一个item布局,这个比较简单
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@id/tv_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="25sp" android:layout_toLeftOf="@id/drag_handle" /> <ImageView android:id="@id/drag_handle" android:background="@drawable/item_move" android:layout_width="25dp" android:layout_height="25dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" /> </RelativeLayout>
这个布局只需要注意,取名不是用@+id 而是直接@id,这里的id需要在ids文件中声明。
再接下来就是调用了,在mainactivity中调用该项目,此时注意需要声明拖动和删除的方法
我写的码如下
public class MainActivity extends Activity { //声明这个activity Event selectedEvent = new Event(); MyAdapter adapter; //声明我的适配器 List<Event> data = new ArrayList<Event>(); //申明我用来存储数据的list DragSortListView.DropListener onDrop = new DragSortListView.DropListener() { @Override public void drop(int from, int to) {//from to 分别表示 被拖动控件原位置 和目标位置 if (from != to) { Event item = (Event) adapter.getItem(from);//得到listview的适配器 adapter.notifyDataSetChanged(); adapter.remove(from);//在适配器中”原位置“的数据。 adapter.insert(item, to);//在目标位置中插入被拖动的控件。 } } }; DragSortListView.RemoveListener onRemove = new DragSortListView.RemoveListener() { @Override public void remove(int which) { adapter.remove(which); } }; protected void onCreate(Bundle savedInstanceState) { //activity类必须有的方法 super.onCreate(savedInstanceState); //继承父类的onCreat方法 setContentView(R.layout.activity_main2); //表明这个Activity对应的布局是 main initData(); DragSortListView listView = (DragSortListView) findViewById(R.id.dslvList); //声明了listview然后绑定id listView.setDropListener(onDrop); listView.setRemoveListener(onRemove); //调用下面的 listEvent方法 adapter = new MyAdapter(MainActivity.this, data); adapter.notifyDataSetChanged(); listView.setAdapter(adapter); } private void initData() { SQLiteHelper helper = ((EventApplication) getApplication()).getSQLiteHelper(); SQLiteDatabase database = helper.open(); data.clear(); data = Event.getAll(database); helper.close(); } }到这里,这个listview 应该就可以使用了,希望对大家有帮助。