android画布之拖拽删除,Android条目拖拽删除功能实例代码

项目中需求,要做条目条目拖拽删除效果,实际效果和QQ消息删除一样,侧滑有制定和删除。

效果图

5527a4fbab048a06816469bfc8af59b5.png

第一步效果图

244fc8470feabe53b95212ac5e8ac781.png

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分析事件

具体代码:

布局:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="wrap_content">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="#fff"

android:orientation="horizontal">

android:id="@+id/item_tv_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:padding="10dp"

android:text="张三"

android:textSize="20sp" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#888888"

android:padding="10dp"

android:text="呼叫"

android:textSize="20sp" />

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="#f00"

android:padding="10dp"

android:text="删除"

android:textSize="20sp" />

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

left=-mRang;

}

}else{

if (left>mWith){//mWith是屏幕的宽度

left=mWith;

}else if (left

left=mWith-mRang;

}

}

return left;

}

第三步:

效果图

a9d1c2af008397a9660f73e79d3db269.png

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条目拖拽删除功能实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值