一、准备。
1.需求问题
初步:实现列表的拖拽效果(可参考Android源码下packages/apps/Music中的播放列表TouchInterceptor.java源码)。
(提前说明一下,本文不是完全按照Music中实现的,代码实现方式做了一些调整,去掉来很多无关的东西,方便大家理解,效果上也修改成了另外一种个人认为是更简单更高效的一套。)
拓展:借鉴上一篇文章Android学习系列(9)--App列表之分组ListView,实现分组列表的拖拽效果。
下面以初步实现为例子,逐步展开实现步骤。
2.搭建主界面DragListActivity.java和主布局drag_list_activity.xml。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class DragListActivity
extends Activity
{
private List<String>
list = null ;
private DragListAdapter
adapter = null ;
public static List<String>
groupKey= new ArrayList<String>();
private List<String>
navList = new ArrayList<String>();
private List<String>
moreList = new ArrayList<String>();
@Override
public void onCreate(Bundle
savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.drag_list_activity);
initData();
DragListView
dragListView = (DragListView)findViewById(R.id.drag_list);
adapter
= new DragListAdapter( this ,
list);
dragListView.setAdapter(adapter);
}
}
|
3.列表项的布局drag_list_item.xml。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<? xml version = "1.0" encoding = "utf-8" ?>
android:layout_width = "fill_parent"
android:layout_height = "wrap_content" >
< TextView
android:id = "@+id/drag_list_item_text"
android:layout_width = "wrap_content"
android:layout_height = "@dimen/drag_item_normal_height"
android:paddingLeft = "5dip"
android:layout_alignParentLeft = "true"
android:layout_centerVertical = "true"
android:gravity = "center_vertical" />
< ImageView android:id = "@+id/drag_list_item_image"
android:src = "@drawable/list_icon"
android:layout_alignParentRight = "true"
android:layout_centerVertical = "true"
android:layout_width = "wrap_content"
android:layout_height = "@dimen/drag_item_normal_height" />
</ RelativeLayout >
|
4.准备样本数据。
我已经准备好了两组数据,在前面提到的initData()方法中执行初始化。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public void initData(){
list
= new ArrayList<String>();
groupKey.add( "A组" );
groupKey.add( "B组" );
for ( int i= 0 ;
i< 5 ;
i++){
navList.add( "A选项" +i);
}
list.add( "A组" );
list.addAll(navList);
for ( int i= 0 ;
i< 8 ;
i++){
moreList.add( "B选项" +i);
}
list.add( "B组" );
list.addAll(moreList);
}
|
这里定义了分组标签集合groupKey后面分组的时候会用到。
5.自定义适配器类DragListAdapter。
接着我们搭建数据适配器,负责把list的数据填充到ListView中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public static class DragListAdapter
extends ArrayAdapter<String>{
public DragListAdapter(Context
context, List<String> objects) {
super (context,
0 ,
objects);
}
@Override
public View
getView( int position,
View convertView, ViewGroup parent) {
View
view = convertView;
if (view== null ){
view
= LayoutInflater.from(getContext()).inflate(R.layout.drag_list_item, null );
}
TextView
textView = (TextView)view.findViewById(R.id.drag_list_item_text);
textView.setText(getItem(position));
return view;
}
}
|
注意getItem(position)会取得数组适配器中position位置的T(这里是字符串),比较好用的一个方法。
至此,我们准备了一个正常的数据列表,效果如下:
二、实现
上面部分是我们的一个 准备工作,接下来我们通过自定义ListView,重写ListView中onInterceptTouchEvent(),onTouchEvent()方法来响应触控事件做相应的界面调整(选中,拖动,数据更改后刷新界面)等等。
6.自定义视图类。
1
2
3
4
5
6
7
8
9
10
11
|
public class DragListView
extends ListView
{
private int scaledTouchSlop;
public DragListView(Context
context, AttributeSet attrs) {
super (context,
attrs);
scaledTouchSlop
= ViewConfiguration.get(context).getScaledTouchSlop();
}
}
|
7.重写触控拦截事件方法onInterceptTouchEvent()。
为了能在子控件响应触摸事件的情况下此ListView也能监听到触摸事件,我们把重写这个方法,做一些初始化工作。我们在这里捕获down事件,在down事件中,我们做一些拖动的准备工作:
1)获取点击数据项,初始化一些变量;
2)判断是否是拖动还是仅仅点击;
3)如果是拖动,建立拖动影像;
这些工作是我们后面拖动的一个执行基础,非常重要。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
private ImageView
dragImageView;
private int dragSrcPosition;
private int dragPosition;
private int dragPoint;
private int dragOffset;
private WindowManager
windowManager;
private WindowManager.LayoutParams
windowParams;
private int scaledTouchSlop;
private int upScrollBounce;
private int downScrollBounce;
@Override
public boolean onInterceptTouchEvent(MotionEvent
ev) {
if (ev.getAction()==MotionEvent.ACTION_DOWN){
int x
= ( int )ev.getX();
int y
= ( int )ev.getY();
dragSrcPosition
= dragPosition = pointToPosition(x, y);
if (dragPosition==AdapterView.INVALID_POSITION){
return super .onInterceptTouchEvent(ev);
}
ViewGroup
itemView = (ViewGroup) getChildAt(dragPosition-getFirstVisiblePosition());
dragPoint
= y - itemView.getTop();
dragOffset
= ( int )
(ev.getRawY() - y);
View
dragger = itemView.findViewById(R.id.drag_list_item_image);
if (dragger!= null &&x>dragger.getLeft()- 20 ){
upScrollBounce
= Math.min(y-scaledTouchSlop, getHeight()/ 3 );
downScrollBounce
= Math.max(y+scaledTouchSlop, getHeight()* 2 / 3 );
itemView.setDrawingCacheEnabled( true );
Bitmap
bm = Bitmap.createBitmap(itemView.getDrawingCache());
startDrag(bm,
y);
}
return false ;
}
return super .onInterceptTouchEvent(ev);
}
|
看到上面的一大堆变量和操作,你可能有些眼花缭乱,在后面使用的时候回头再去理解也可。 开始拖动影像startDrag()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
/**
*
准备拖动,初始化拖动项的图像
*
@param bm
*
@param y
*/
public void startDrag(Bitmap
bm , int y){
stopDrag();
windowParams
= new WindowManager.LayoutParams();
windowParams.gravity
= Gravity.TOP;
windowParams.x
= 0 ;
windowParams.y
= y - dragPoint + dragOffset;
windowParams.width
= WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.height
= WindowManager.LayoutParams.WRAP_CONTENT;
windowParams.flags
= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
windowParams.format
= PixelFormat.TRANSLUCENT;
windowParams.windowAnimations
= 0 ;
ImageView
imageView = new ImageView(getContext());
imageView.setImageBitmap(bm);
windowManager
= (WindowManager)getContext().getSystemService( "window" );
windowManager.addView(imageView,
windowParams);
dragImageView
= imageView;
}
|
stopDrag()方法如下:
1
2
3
4
5
6
7
8
9
|
/**
*
停止拖动,去除拖动项的头像
*/
public void stopDrag(){
if (dragImageView!= null ){
windowManager.removeView(dragImageView);
dragImageView
= null ;
}
}
|
运行看看,我们点击一项的时候没有什么反应,但是细心观察的话,其实点击项上有一层淡淡的重影,这就是我们定义的点击项的影像,后面要做的就是拖动这个影像,放下影像以及放下位置的数据项插入和原数据项位置的删除,这部分内容以及后续扩展的内容我们放到下篇中继续分析并实现。
分享到:
相关推荐
实现android 列表项 拖拽的效果.....原文: App列表之拖拽ListView源码(上) http://www.cnblogs.com/qianxudetianxia/archive/2011/06/12/2068761.html App列表之拖拽ListView源码(下) ...
本文实例讲述了Android开发实现可拖动排序的ListView功能。分享给大家供大家参考,具体如下: 一、上图 二、简述 1、需要实现的效果是长按右侧可拖动部分布局实现列表项的拖动排序 2、当点击列表项前面的单选按钮时...
Android应用源码开发Demo,主要用于毕业设计学习。
ListView 中的item随意拖动.zip
Android应用源码开发Demo,主要用于毕业设计学习。
listview 下拉刷新页面标题带着可往下拖动。
包括卡片式列表(效果图1),Grid View列表(效果图2),列表item逐个淡入显示(效果图3),拖动列表item重新排序(效果图4),滑动删除列表item(效果图5),批量删除列表item(效果图6),展开列表item(效果图7)...
Android的ListView是应用最广的一个组件,功能强大,扩展性灵活(不局限于ListView本身一个类),前面的文章有介绍分组,拖拽,3D立体,游标,圆角,而今天我们要介绍的是另外一个扩展ListView:下拉刷新的ListView。...
Android RecycleView+任意头尾布局+拖拽换位+拖拽删除demo Android sql练习合集 Android 仿12306 Android 优秀计步器 Android 体重计算源码 Android 使用Gallery_tabhost实现标签效果图源码 Android 例子源码根据CPU...
强大的Android下拉刷新框支持下拉刷新、上拉加载、二级刷新、越界回弹、越界拖动,具有极强的扩展性,并集成了几十种炫酷的Header和 Footer。 支持横向刷新 支持多点触摸 支持淘宝二楼和二级刷新 支持嵌套多层的视图...
Android应用源码开发Demo,主要用于毕业设计学习。
XposedFastScroll Xposed mod 强制所有 ListViews 使用 FastScroll 功能 ... 这对于列表很长的应用程序非常有用,我发现其中一些非常有用: WhatsApp 聊天列表 Super Backup Xposed 安装程序下载列表 我确定还有更多
Android项目源码本站发布的第5个动画源码集项目是一个安卓动画app,包括字体闪烁、抽屉式拖动、listview上拉刷新、翻页效果、二维码扫描、3d图片旋转、通讯录、fragment的滑动添加、android对HTML5的加载、view的...
自己积累和整理的一个安卓动画app,包括字体闪烁、抽屉式拖动、listview上拉刷新、翻页效果、二维码扫描、3d图片旋转、通讯录、fragment的滑动添加、android对HTML5的加载、view的开门动画、镜头由远及近的效果、...
改变ListView列表项选中状态的背景颜色 102 可展开的列表组件 102 数据的存取 103 SharePreferences 6.1 103 文件的存储6.2 103 SQLite数据库6.4 103 ContentProvider、ContentResolver 6.5 105 Intent 106 用Intent...
另外,因为Design库的推出大大方便我们编写带有Material风格的App,而ListView是不兼容这个库的,比如滑动的相互协调,只有RecyclerView能做到。 先看本篇内容的效果图: 效果内容主要有三部分: •长按点击...
介绍 学习Android开发的代码,基于AndroidStudio View_Demo是Android基础控件和布局,包括TextView,Edittext,ImageView,Button,RadioButton,Checkbox,ProgressBar和拖动条。 Adapter_Demo 是Adapter相关的代码...
Android 小項目之---Iphone拖动图片特效 (附源码) 一个完整的新浪微博客户端android版OAuth认证示例 超爽的android抽屉效果 65个Android实例教程汇总 基本控件及基本动画效果dem 2011android面试题目及其答案大全...