Android条目拖拽删除功能实例代码
项目中需求,要做条目条目拖拽删除效果,实际效果和qq消息删除一样,侧滑有制定和删除。
效果图
第一步效果图
1.0自定义控件 swipelayout 继承framelayout重写里面三个构造方法,分别调用initview().
2.0在布局中使用自定义控件
3.0在initview()方法中,创建拖拽辅辅助工具 viewdraghelper()
该方法需要传入回调 mycallback()
4.0,创建mycallback()回调,继承viewdraghelper.callback
在回调中 覆盖trycaptureview方法,返回true 允许child被拖拽,被 覆盖clampviewpositionhorizontal 返回left系统提供拖拽位置
5.0 onintercepttouchevent 返回:让viewdraghelper判断是否需要拦截事件
6.0 ontouchevent 返回true 并且让viewdraghelper分析事件
具体代码:
布局:
<cn.itheima.swipelayout.swipelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="wrap_content"> <!--正文部分--> <relativelayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#fff" android:orientation="horizontal"> <textview android:id="@+id/item_tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="10dp" android:text="张三" android:textsize="20sp" /> </relativelayout> <!--按钮部分--> <linearlayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#888888" android:padding="10dp" android:text="呼叫" android:textsize="20sp" /> <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#f00" android:padding="10dp" android:text="删除" android:textsize="20sp" /> </linearlayout> </cn.itheima.swipelayout.swipelayout>
swipelayout 代码:
public class swipelayout extends framelayout { private viewdraghelper mdraghelper; public swipelayout(context context) { super(context); initview(); } public swipelayout(context context, attributeset attrs) { super(context, attrs); initview(); } public swipelayout(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); initview(); } private void initview() { mdraghelper = viewdraghelper.create(this,new mycallback()); } // 让viewdraghelper就是拖拽辅助工具 返回true 则表示要拦截触摸事件 @override public boolean onintercepttouchevent(motionevent ev) { //让拖拽辅助工具判断是否需要拦截 事件 return mdraghelper.shouldintercepttouchevent(ev); } @override public boolean ontouchevent(motionevent event) { //让拖拽辅助工具分析事件 分析用户手势 mdraghelper.processtouchevent(event); return true; } private class mycallback extends viewdraghelper.callback{ /** * 如果返回 true 则表示 child 允许被拖拽 */ @override public boolean trycaptureview(view child, int pointerid) { return true; } /** * 固定被拖拽控件的水平位置, * 参数里的 left 是系统推荐移动到的位置,可以进行修正, * 方法返回的值就是 child 将要移动到的位置 */ @override public int clampviewpositionhorizontal(view child, int left, int dx) { return left; } } }
第二步:
1.0创建onfinishinflate方法获取子控件,并且判断健壮性
/* 控件初始化时执行,可以用于获取子控件 */ @override protected void onfinishinflate() { // 健壮性检查 if (getchildcount()!=2){ throw new runtimeexception("swipelayout 必须存放两个子控件"); } if (!(getchildat(0) instanceof viewgroup)||!(getchildat(1) instanceof viewgroup)){ throw new runtimeexception("swipelayout 的子控件必须是 viewgroup"); } mcontent = (viewgroup) getchildat(0); mdeletepanel = (viewgroup) getchildat(1); }
2.0创建onsizechanged方法,在控件大小改变的时候调用,获取控件的宽高,和删除的面板的最大移动范围
/** * 当控件大小改变的时候调用这个方法 */ @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(w, h, oldw, oldh); int mwith = w; int mheigth = h; //界面创建过程中,不能使用 getwidth 方法 int mrang = mdeletepanel.getmeasuredwidth(); }
3.0在onlayout中指定侧拉面板的位置
//指定侧拉面板的位置 @override protected void onlayout(boolean changed, int left, int top, int right, int bottom) { super.onlayout(changed, left, top, right, bottom); mdeletepanel.layout(mwith,0,mwith+mrang,mheigth); }
4.0在onviewpositionchanged方法中实现联动效果
/** * 当被拖拽的控件已经移动过后,会调用这个方法,可以用于处理控件间的联动效果 * @left 被拖拽控件的真实移动位置 * @dx 被拖拽控件的真实偏移大小 */ @override public void onviewpositionchanged(view changedview, int left, int top, int dx, int dy) { if (changedview==mcontent){ // 移动正文的同时也要移动侧栏 mdeletepanel.offsetleftandright(dx); }else{ mcontent.offsetleftandright(dx); } }
5.0在 clampviewpositionhorizontal方法中 固定被拖拽控件的水平位置,
/** * 固定被拖拽控件的水平位置, * 参数里的 left 是系统推荐移动到的位置,可以进行修正, * 方法返回的值就是 child 将要移动到的位置 */ @override public int clampviewpositionhorizontal(view child, int left, int dx) { if (child==mcontent){ if (left>0){ left=0; }else if (left<-mrang){ left=-mrang; } }else{ if (left>mwith){//mwith是屏幕的宽度 left=mwith; }else if (left<mwith-mrang){ left=mwith-mrang; } } return left; }
第三步:
效果图
1.0onviewreleased中根据来开局里面,判断是否打开还是关闭
2.0 在 movecontent中第一次滑动
3.0computescroll中,继续滑动,直到滑动到指定的位置
4.0注意在onviewpositionchanged中手动刷新界面,调用invalidate方法
如果不手动刷新界面,效果展示不出来
/** * 当用户松手时执行 * @xvel 松手时在 x 方向的移动速度,如果为 正数 则说明是向右移动,如果是 负数 则说明是向左移动,如果为零,说明是静止状态 */ @override public void onviewreleased(view releasedchild, float xvel, float yvel) { if (xvel>0){ //向右移动 close(); }else if (xvel<0){ //向左移动 opend(); }else if (xvel>-mrang/2){// 静止状态 close();// 展开不到一半,关闭面板 }else{ opend(); } } } /** * 打开面板 */ private void opend() { int left=-mrang; movecontent(left); } /** * 关闭面板 */ private void close() { int left=0; movecontent(left); } private void movecontent(int left) { // 开启平滑滚动,如果返回 true 则说明要继续刷新界面,保持滚动 if(mdraghelper.smoothslideviewto(mcontent,left,0)){ invalidate(); } } @override public void computescroll() { // 继续平滑滚动,如果返回 true 则说明要继续刷新界面,保持滚动 if (mdraghelper.continuesettling(true)){ invalidate(); } }
第四步:
1.0现给listview赋值 在这就省略
2.0在swipelayout中使用枚举记录面板的状态
private enum status{ closed,opened,draging; } private status status = status.closed; public status getstatus() { return status; }
3.0// 记录上一个打开的面板。注意:一定要是 静态变量
private static swipelayout preswipelayout;
4.0在onviewpositionchanged中创建一个方法操作关闭面板
// 关闭上一个打开的面板 closepre();
5.0closepre()在这个方法中,判断当前面板的状态,并且根据状态,关闭上一个打开的面板
// 判断当前面板是否正在打开,如果正在打开则将上一个打开的面板关闭 private void closepre() { //记录旧状态 status prestatus=status; if (mcontent.getleft()==-mrang){ //记录当前面板已经打开 status=status.opened; }else if (mcontent.getleft()==0){ //当前面板已经关闭 status=status.closed; }else { status=status.draging; } // 如果当前面板旧状态为关闭,并且新状态为拖拽,那么此时可以关闭之前打开的面板 if (prestatus==status.closed&&status==status.draging){ if (preswipelayout!=null&&preswipelayout!=this){ // 关闭上一个面板 preswipelayout.close(); } // 将当前面板标记为 打开的面板 preswipelayout=this; } }
总结
以上所述是小编给大家介绍的android条目拖拽删除功能实例代码,希望对大家有所帮助