900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Android开发--自定义控件实现listview的滑动删除item

Android开发--自定义控件实现listview的滑动删除item

时间:2023-02-18 17:52:12

相关推荐

Android开发--自定义控件实现listview的滑动删除item

首先我们在日常的软件使用中已经有很多这样的例子了,例如我们用到的QQ、微信都具有这样的功能。而本文只是简单的起一个引导的作用,在已经存在的listview的基础上对其进行改造,使它能更好的满足

我们在开发当中遇到的需求。

首先,我们先看下我们要达到的效果:

看到效果图,首先我们来思考一下,要实现这样的效果,我们需要进行怎样的步骤?

思路:可以确定的是,我们肯定通过手势的从右自左的滑动,这样,我们就想肯定要获取到滑动之前的X,Y坐标和滑动结束的X,Y坐标。

通过判断开始和结束时坐标距离的绝对值来计算出滑动的距离。在这之前,我们应该设置一个值,来表示当大于这个值时。

我们就应该响应滑动事件,及显示删除按钮。如何显示一个删除按钮呢?我们这儿采用Android自带的一个控件:PopupWindow。

通过上面简单的分析之后,我们就来看具体的代码实现。然后在慢慢了解编码过程中,我们需要注意的细节问题。

首先,来看下目录结构:

准备两个布局文件:1、activity_main.xml 主界面布局文件。2、btn_delete.xml Button删除按钮的布局文件

下面是布局文件的具体代码实现:

activity_main.xml:

[html]

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayout

xmlns:android="/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent">

<com.hql.listviewitemdelete.widget.ListViewDeleteItem

android:id="@+id/list_item_delete"

android:layout_width="match_parent"

android:layout_height="match_parent">

</com.hql.listviewitemdelete.widget.ListViewDeleteItem>

</LinearLayout>

btn_delete.xml:

[html]

<?xmlversion="1.0"encoding="utf-8"?>

<Button

android:id="@+id/btn_delete"

xmlns:android="/apk/res/android"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#ff0202"

android:text="删除"/>

布局文件都很简单,相信大家都能看得懂。

接下来,我们就来编写ListViewDeleteItem,这个类,因为我们是在listview进行扩展开发,所以我们应该是继承自listview。

[java]

/**

*listview滑动删除item

*CreatedbyMr.Hon/11/16.

*/

publicclassListViewDeleteItemextendsListView

接下来我们根据刚刚的思路,首先应该定义一下变量:开始X,Y坐标、结束X,Y坐标、相应滑动的距离、是否正在滑动、布局加载器、

PopupWindow、PopupWindow宽高、删除按钮Button、删除按钮的回调接口、手指现在触摸到的view、和手指触摸到的view的位置。

以上就是我们应该要定义的成员变量。

[java]

//手指按下的X,Y坐标

privateintstartX;

privateintstartY;

//手指移动结束时的X,Y坐标

privateintendX;

privateintendY;

//用户手势滑动的距离

privateintmoveLength;

//是否正在滑动

privatebooleanisSliding;

//布局加载器

privateLayoutInflatermInflater;

//pop弹出

privatePopupWindowmPopupWindow;

//pop高度

privateintmPopupWindowHeight;

//pop宽度

privateintmPopupWindowWidth;

//删除按钮

privateButtonmBtnDelete;

//删除按钮的回调接口

publicBtnDeleteClickListenermListener;

//当前手指触摸的View

privateViewmCurrentView;

//当前手指触摸的位置

privateintmCurrentViewPos;

现在我们需要重写含有两个参数的构造方法,并对部分变量就行初始化。

[java]

publicListViewDeleteItem(Contextcontext,AttributeSetattrs)

{

super(context,attrs);

//实例化布局加载器

mInflater=LayoutInflater.from(context);

//getScaledTouchSlop是一个距离,表示滑动的时候,手的移动要大于这个距离才开始移动控件,如果小于这个距离就不触发移动控件。

moveLength=ViewConfiguration.get(context).getScaledTouchSlop();

//获取到删除按钮的布局文件

Viewview=mInflater.inflate(R.layout.btn_delete,null);

//查找删除按钮

mBtnDelete=(Button)view.findViewById(R.id.btn_delete);

//实例化POP,并且绑定视图,和设置宽高

mPopupWindow=newPopupWindow(view,LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);

//先调用下measure,否则拿不到宽和高

mPopupWindow.getContentView().measure(0,0);

//获取button的宽高

mPopupWindowHeight=mPopupWindow.getContentView().getMeasuredHeight();

mPopupWindowWidth=mPopupWindow.getContentView().getMeasuredWidth();

}

上面的主要是对布局加载器进行初始化,加载一个布局文件,然后绑定到PopupWindow中,并且测出button在PopupWindow中的宽高。

做完以上操作,我们现在就需要实现我们最重要的部分了,即手势的判断。

接下来我们重写dispatchTouchEvent(MotionEvent ev)这个方法。这个方法主要是对点击事件的分发。

首先,我们通过ev这个参数来获取到用户的点击事件类型,并且用两个局部变量,记录下点击时的X,Y坐标。

[java]

//获取点击类型

intactiion=ev.getAction();

//获取按下时的x,y坐标

intx=(int)ev.getX();

inty=(int)ev.getY();

对此,我们应该判断用户的两个动作:按下和移动

首先我们先来看按下事件的处理:

[java]

switch(actiion)

{

//按下

caseMotionEvent.ACTION_DOWN:

startX=x;

startY=y;

//如果当前的pop显示,则将其隐藏掉

if(mPopupWindow.isShowing())

{

dismissPopWindow();

returnfalse;

}

//获得当前手指按下时的item的位置

mCurrentViewPos=pointToPosition(startX,startY);

//获得当前手指按下时的item

Viewview=getChildAt(mCurrentViewPos-getFirstVisiblePosition());

mCurrentView=view;

break;

将开始获取到的X,Y坐标赋值给定义的变量。并且判断PopupWindow是否正在显示,如果是则关闭,并且返回false。

之后通过pointToPosition()方法获取到当前按下的item的位置。通过getChildAt()获取到当前点击item位置所对应的view。

以上就是用户按下的事件。

下面来处理用户移动时的事件。

[java]

//移动

caseMotionEvent.ACTION_MOVE:

endX=x;

endY=y;

intdx=endX-startX;

intdy=endY-startY;

/**

*判断是否是从右到左的滑动

*/

if(endX<startX&&Math.abs(dx)>moveLength&&Math.abs(dy)<moveLength)

{

isSliding=true;

}

break;

上面是对事件的分发处理,下面我们就来看看事件的处理即:onTouchEvent(MotionEvent ev)方法。

[java]

intaction=ev.getAction();

if(isSliding)

{

switch(action)

{

caseMotionEvent.ACTION_UP:

isSliding=false;

break;

caseMotionEvent.ACTION_MOVE:

int[]location=newint[2];

mCurrentView.getLocationOnScreen(location);

//设置pop显示的位置

mPopupWindow.showAtLocation

(mCurrentView,Gravity.LEFT|Gravity.TOP,

location[0]+mCurrentView.getWidth(),

location[1]+mCurrentView.getHeight()/2-mPopupWindowHeight/2);

mBtnDelete.setOnClickListener(newOnClickListener()

{

@Override

publicvoidonClick(Viewview)

{

if(mListener!=null)

{

mListener.btnClick(mCurrentViewPos);

mPopupWindow.dismiss();

}

}

});

break;

}

}

returnsuper.onTouchEvent(ev);

首先,我还是要先获取到用户的点击事件类型,并且判断是否正在移动,当用户手势抬起的时候,将是否正在滑动设置为false。

处理用户移动的事件,设置PopupWindow的显示位置,并且给button设置点击事件。

[java]

publicvoidsetBtnDeleteClickListener(BtnDeleteClickListenerlistener)

{

mListener=listener;

}

publicinterfaceBtnDeleteClickListener

{

voidbtnClick(intposition);

}

/**

*隐藏pop

*/

privatevoiddismissPopWindow()

{

if(mPopupWindow!=null&&mPopupWindow.isShowing())

{

mPopupWindow.dismiss();

}

}

上面就是定义一个接口并写隐藏pop的方法。以上全部就是自定义的全部代码。接下来只需要将其写到布局文件当中。

demo下载地址:/detail/poison_h/9275487

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。