侧拉删除
来源:互联网 发布:出租淘宝号的平台 编辑:程序博客网 时间:2024/04/28 18:45
先给大家分享一下,侧滑删除,布局也就是前面一个item,然后有两个隐藏的按钮(TextView也可以),然后我们可以向左侧滑动,然后显示出来,然后对delete(删除键)实现监听,就可以了哈。好了那就来看看代码怎么实现的吧。
首先和之前一样
自定义View,初始化ViewDragHelper:
package
com.example.removesidepull;
import
android.content.Context;
import
android.support.v4.widget.ViewDragHelper;
import
android.util.AttributeSet;
import
android.view.MotionEvent;
import
android.view.View;
import
android.widget.FrameLayout;
/**
* Created by 若兰 on 2016/2/2.
* 一个懂得了编程乐趣的小白,希望自己
* 能够在这个道路上走的很远,也希望自己学习到的
* 知识可以帮助更多的人,分享就是学习的一种乐趣
* QQ:1069584784
* csdn:http://blog.csdn.net/wuyinlei
*/
public
class
SwipeLayout
extends
FrameLayout {
private
ViewDragHelper mDragHelper;
public
SwipeLayout(Context context) {
this
(context,
null
);
}
public
SwipeLayout(Context context, AttributeSet attrs) {
this
(context, attrs,
0
);
}
public
SwipeLayout(Context context, AttributeSet attrs,
int
defStyleAttr) {
super
(context, attrs, defStyleAttr);
//第一步 初始化ViewDragHelper
mDragHelper = ViewDragHelper.create(
this
, mCallback);
}
ViewDragHelper.Callback mCallback =
new
ViewDragHelper.Callback() {
@Override
public
boolean
tryCaptureView(View child,
int
pointerId) {
//返回true
return
true
;
}
};
}
然后我们就要去处理拦截事件也就是重写一些onInterceptTouchEvent和onTouchEvent方法,默认是不拦截的:
/**
* 传递触摸事件
*
* @param ev
* @return
*/
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
//交给ViewDragHelper判断是否去拦截事件
return
mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
try
{
mDragHelper.processTouchEvent(event);
}
catch
(Exception e) {
e.printStackTrace();
}
//返回true,这里表示去拦截事件
return
true
;
}
然后我们去重写一下ViewDragHelper里面的clampViewPositionHorizontal方法:
@Override
public
int
clampViewPositionHorizontal(View child,
int
left,
int
dx) {
return
left;
}
好了这个时候,就已经可以实现滑动了,我们先来看下结果:
这里我们可以看到,已经可以滑动了,好了接下来的就是要处理滑动事件,去放置到正确的地方(call me 和删除刚开始不能见,还有只能左滑显示,右滑隐藏)。
好了,我们先获取两个View吧:
/**
* 当xml填充完毕的时候
*/
@Override
protected
void
onFinishInflate() {
super
.onFinishInflate();
/**
* 后view
*/
mBackView = getChildAt(
0
);
/**
* 前view
*/
mFrontView = getChildAt(
1
);
}
获取想要的宽和高:
/**
* 在这里获取宽和高
*
* @param w
* @param h
* @param oldw
* @param oldh
*/
@Override
protected
void
onSizeChanged(
int
w,
int
h,
int
oldw,
int
oldh) {
super
.onSizeChanged(w, h, oldw, oldh);
/**
* 高度
*/
mHeight = mFrontView.getMeasuredHeight();
/**
* 宽度
*/
mWidth = mFrontView.getMeasuredWidth();
/**
* 移动距离
*/
mRange = mBackView.getMeasuredWidth();
}
摆放这两个view的位置:
/**
* 摆放位置
* @param changed
* @param left
* @param top
* @param right
* @param bottom
*/
@Override
protected
void
onLayout(
boolean
changed,
int
left,
int
top,
int
right,
int
bottom) {
super
.onLayout(changed, left, top, right, bottom);
layoutContent(
false
);
}
private
void
layoutContent(
boolean
isOpen) {
//摆放前view
Rect frontRect = computeFrontViewRect(isOpen);
mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom);
//摆放后view
Rect backRect = computeBackViewRect(frontRect);
mBackView.layout(backRect.left,backRect.top,backRect.right,backRect.bottom);
//前置前view
bringChildToFront(mFrontView);
}
/**
* 我们可以把前view相当于一个矩形
*
* @param frontRect
* @return
*/
private
Rect computeBackViewRect(Rect frontRect) {
int
left = frontRect.right;
return
new
Rect(left,
0
, left + mRange,
0
+ mHeight);
}
private
Rect computeFrontViewRect(
boolean
isOpen) {
int
left =
0
;
if
(isOpen) {
left = -mRange;
}
return
new
Rect(left,
0
, left + mWidth,
0
+ mHeight);
}
当然这个实现,只是可以拖拽了前view,因为我们没有把改变的dx传递下去,好了来实现拖拽前view的时候,后view也跟着出来(ViewDragHelper里面的方法):
/**
* 当view位置改变的时候
* @param changedView 改变的view
* @param left
* @param top
* @param dx x轴偏移量
* @param dy
*/
@Override
public
void
onViewPositionChanged(View changedView,
int
left,
int
top,
int
dx,
int
dy) {
super
.onViewPositionChanged(changedView, left, top, dx, dy);
//传递事件,如果是拖拽的前view,
if
(changedView == mFrontView){
//Offset this view's horizontal location by the specified amount of pixels.
//也就是说我的我的前view左滑了dx,那么我的后view也是左滑dx,右滑同理
mBackView.offsetLeftAndRight(dx);
}
else
if
(changedView == mBackView){
//拖拽的是后view的话,前View的处理方式一样
mFrontView.offsetLeftAndRight(dx);
}
//兼容老版本
invalidate();
}
好了这个时候我们来看下效果:
是不是发现了问题,就是我的前view想要的结果是不能右滑的(只允许左滑和返回),那么接下来就实现这个想要的结果吧。以下的代码是在clampViewPositionHorizontal()方法里面:
//在这里处理放置的逻辑拖拽的前view
if
(child == mFrontView) {
if
(left >
0
) {
return
0
;
}
else
if
(left < -mRange) {
return
-mRange;
}
}
//拖拽的后view
else
if
(child == mBackView) {
if
(left > mWidth) {
return
mWidth;
}
else
if
(left < mWidth - mRange) {
return
mWidth - mRange;
}
}
看下效果图:
好了,这个时候已经基本实现了,接下来实现以下滑动的距离和速度【判断是否打开和关闭:
/**
* 拖拽的view释放的时候
*
* @param releasedChild
* @param xvel
* @param yvel
*/
@Override
public
void
onViewReleased(View releasedChild,
float
xvel,
float
yvel) {
if
(xvel ==
0
&& mFrontView.getLeft() < -mRange /
2
.0f) {
open();
}
else
if
(xvel <
0
) {
open();
}
else
{
close();
}
}
/**
* 关闭
*/
public
void
close() {
Utils.showToast(getContext(),
"close"
);
layoutContent(
false
);
}
//打开
public
void
open() {
//Utils.showToast(getContext(), "open");
layoutContent(
true
);
}
好了,接下来实现以下平滑的关闭和打开:
public
void
close() {
close(
true
);
}
/**
* 关闭
*
* @param isSmooth
*/
public
void
close(
boolean
isSmooth) {
int
finalLeft =
0
;
if
(isSmooth) {
//开始动画 如果返回true表示没有完成动画
if
(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft,
0
)) {
ViewCompat.postInvalidateOnAnimation(
this
);
}
}
else
{
layoutContent(
false
);
}
}
public
void
open() {
open(
true
);
}
/**
* 打开
*
* @param isSmooth
*/
public
void
open(
boolean
isSmooth) {
int
finalLeft = -mRange;
if
(isSmooth) {
//开始动画
if
(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft,
0
)) {
ViewCompat.postInvalidateOnAnimation(
this
);
}
}
else
{
layoutContent(
true
);
}
}
/**
* 持续动画
*/
@Override
public
void
computeScroll() {
super
.computeScroll();
//这个是固定的
if
(mDragHelper.continueSettling(
true
)) {
ViewCompat.postInvalidateOnAnimation(
this
);
}
}
我们看下最终的效果吧:
好了,在这里我们加上一些回调,以方便外部使用的时候可以回调:
/**
* 默认状态是关闭
*/
private
Status status = Status.Close;
private
OnSwipeLayoutListener swipeLayoutListener;
public
Status getStatus() {
return
status;
}
public
void
setStatus(Status status) {
this
.status = status;
}
public
OnSwipeLayoutListener getSwipeLayoutListener() {
return
swipeLayoutListener;
}
public
void
setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) {
this
.swipeLayoutListener = swipeLayoutListener;
}
/**
* 定义三种状态
*/
public
enum
Status {
Close, Open, Draging
}
/**
* 定义回调接口 这个在我们
*/
public
interface
OnSwipeLayoutListener {
/**
* 关闭
*
* @param mSwipeLayout
*/
void
onClose(SwipeLayout mSwipeLayout);
/**
* 打开
*
* @param mSwipeLayout
*/
void
onOpen(SwipeLayout mSwipeLayout);
/**
* 绘制
*
* @param mSwipeLayout
*/
void
onDraging(SwipeLayout mSwipeLayout);
/**
* 要去关闭
*/
void
onStartClose(SwipeLayout mSwipeLayout);
/**
* 要去开启
*/
void
onStartOpen(SwipeLayout mSwipeLayout);
}
dispatchSwipeEvent()方法(在onViewPositionChanged()方法中调用)
protected
void
dispatchSwipeEvent() {
//判断是否为空
if
(swipeLayoutListener !=
null
) {
swipeLayoutListener.onDraging(
this
);
}
// 记录上一次的状态
Status preStatus = status;
// 更新当前状态
status = updateStatus();
if
(preStatus != status && swipeLayoutListener !=
null
) {
if
(status == Status.Close) {
swipeLayoutListener.onClose(
this
);
}
else
if
(status == Status.Open) {
swipeLayoutListener.onOpen(
this
);
}
else
if
(status == Status.Draging) {
if
(preStatus == Status.Close) {
swipeLayoutListener.onStartOpen(
this
);
}
else
if
(preStatus == Status.Open) {
swipeLayoutListener.onStartClose(
this
);
}
}
}
}
updateStatus()方法:
/**
* 更新状态
*
* @return
*/
private
Status updateStatus() {
//得到前view的左边位置
int
left = mFrontView.getLeft();
if
(left ==
0
) {
//如果位置是0,就是关闭状态
return
Status.Close;
}
else
if
(left == -mRange) {
//如果左侧边距是后view的宽度的负值,状态为开
return
Status.Open;
}
//其他状态就是拖拽
return
Status.Draging;
}
好了,事件基本上已经实现完毕了,这个侧拉删除的我会更新至我的项目中,同时希望Android高仿QQ6.0侧滑删除实例代码对大家有所帮助。
- 侧拉删除
- TableView侧拉删除
- 侧拉删除
- 侧拉删除
- 类 QQ 侧拉删除
- 仿QQ侧拉删除
- 自定义控件:侧拉删除
- 自定义侧拉删除(嵌套ListView)
- 自定义SwipeLayout侧拉删除控件
- Android开发之高仿QQ消息侧拉删除
- 侧滑删除,下拉刷新,上拉加载
- 条目的侧拉删除----仿照微信
- listview下拉刷新+上拉自动加载+侧滑删除
- 自定义侧拉删除(没有嵌套ListView)
- 鹅厂系列二 : 仿QQ侧拉删除
- 侧拉
- 侧拉
- 侧拉
- 【Java进阶二】理解继承
- Android插件化浅析
- LeetCode 第 67 题 (Add Binary)
- R-CNN随笔No.3
- 3.Oracle SQL函数
- 侧拉删除
- 4.Oracle表空间
- ubuntu sudo apt-get update 失败
- MySQL Server 5.7 安装记录
- 基于历史数据查询的爬虫操作
- ubunbu中文输入法安装
- unity触摸放大缩小旋转
- 5.Oracle用户管理
- HDU-5707-Combine String【2016CCPC女生专场】【DP】