版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】Android中如何通过ViewDragHelper实现ListView的Item的侧拉划出效果
/upload/information/20200623/125/126976.gif实现该自定义控件的大体步骤如下:/upload/information/20200623/125/126977.png/upload/information/20200623/125/126978.png以上2部分就是该自定义控件要包含的2个直接子View./**
*
Created
by
mChenys
on
2015/12/26.
*/
public
class
SwipeLayout
extends
FrameLayout
{
private
ViewDragHelper.Callback
mCallback;
private
ViewDragHelper
mDragHelper;
private
View
mBackView;
//item的侧边布局
private
View
mFrontView;//当前显示的item布局
private
int
mWidth;
//屏幕的宽度,mFrontView的宽度
private
int
mHeight;
//mFrontView的高度
private
int
mRange;//mFrontView侧拉时向左移动的最大距离,即mBackView的宽度
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);
init();
}
//1.初始ViewDragHelper
private
void
init()
{
mCallback
=
new
ViewDragHelper.Callback()
{
//3.在回调方法中处理触摸事件
@Override
public
boolean
tryCaptureView(View
child,
int
pointerId)
{
return
true;
//允许所有子控件的滑动
}
//设定滑动的边界值
@Override
public
int
clampViewPositionHorizontal(View
child,
int
left,
int
dx)
{
if
(child
==
mFrontView)
{
//前景View的滑动范围是(0~
-mRange)
if
(left
>
0)
{
left
=
0;
}
else
if
(left
<
-mRange)
{
left
=
-mRange;
}
}
if
(child
==
mBackView)
{
//背景View的滑动范围是(mWidth
-
mRange
~
mWidth)
if
(left
>
mWidth)
{
left
=
mWidth;
}
else
if
(left
<
(mWidth
-
mRange))
{
left
=
mWidth
-
mRange;
}
}
//返回修正过的建议值
return
left;
}
//监听View的滑动位置的改变,同步前景View和背景View的滑动事件
@Override
public
void
onViewPositionChanged(View
changedView,
int
left,
int
top,
int
dx,
int
dy)
{
if
(changedView
==
mFrontView)
{
//当滑动前景View时,也需要滑动背景View
mBackView.offsetLeftAndRight(dx);
}
else
if
(changedView
==
mBackView)
{
//当滑动背景View时,也需要滑动前景View
mFrontView.offsetLeftAndRight(dx);
}
//
兼容老版本
invalidate();
}
//处理释放后的开启和关闭动作
@Override
public
void
onViewReleased(View
releasedChild,
float
xvel,
float
yvel)
{
if
(xvel
<
0)
{
//有向左滑动的速度,则打开
open();
}
else
if
(xvel
==
0
&&
mFrontView.getLeft()
<
-mRange
/
2.0f)
{
//前景View向左滑动的left小于背景View宽度一半的负值时,打开
open();
}
else
{
//其他情况为关闭
close();
}
}
};
mDragHelper
=
ViewDragHelper.create(this,
mCallback);
}
//2.传递触摸事件
@Override
public
boolean
onInterceptTouchEvent(MotionEvent
ev)
{
return
mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public
boolean
onTouchEvent(MotionEvent
event)
{
try
{
mDragHcessTouchEvent(event);
}
catch
(Exception
e)
{
e.printStackTrace();
}
return
true;
}
//获取子控件的引用
@Override
protected
void
onFinishInflate()
{
super.onFinishInflate();
mBackView
=
getChildAt(0);
//获取背景View,即展示数据的Item的右边隐藏的侧滑布局
mFrontView
=
getChildAt(1);//获取前景View,即展示数据的Item
}
//获取子控件的相关宽高信息
@Override
protected
void
onSizeChanged(int
w,
int
h,
int
oldw,
int
oldh)
{
super.onSizeChanged(w,
h,
oldw,
oldh);
mWidth
=
mFrontView.getMeasuredWidth();
mHeight
=
mFrontView.getMeasuredHeight();
mRange
=
mBackView.getMeasuredWidth();
}
//确定子控件的初始位置
@Override
protected
void
onLayout(boolean
changed,
int
left,
int
top,
int
right,
int
bottom)
{
super.onLayout(changed,
left,
top,
right,
bottom);
layoutChildView(false);
}
/**
*
放置子控件的位置
*
*
@param
isOpen
是否是打开前景View,true打开,false关闭
*/
private
void
layoutChildView(boolean
isOpen)
{
//计算前景View的位置,将坐标信息封装到矩形中
Rect
fontRect
=
computerFontViewRect(isOpen);
//摆放前景View
mFrontView.layout(fontRect.left,
fontRect.top,
fontRect.right,
fontRect.bottom);
//摆放背景View,left坐标是前景View的right坐标
int
left
=
fontRect.right;
mBackView.layout(left,
0,
left
+
mRange,
mHeight);
//由于上面是后摆放背景View,所以会覆盖前景View,因此需要通过下面的方式将前景View显示在前面
bringChildToFront(mFrontView);
}
/**
*
计算前景View的坐标
*
*
@param
isOpen
是否是打开前景View
*
@return
*/
private
Rect
computerFontViewRect(boolean
isOpen)
{
int
left
=
isOpen
?
-mRange
:
0;
return
new
Rect(left,
0,
left
+
mWidth,
mHeight);
}
/**
*
打开侧边栏mBackView,默认平滑打开
*/
public
void
open()
{
open(true);
}
/**
*
打开侧边栏mBackView
*
*
@param
isSmooth
是否平滑打开
*/
public
void
open(boolean
isSmooth)
{
if
(isSmooth)
{
if
(mDragHelper.smoothSlideViewTo(mFrontView,
-mRange,
0))
{
//动画在继续
ViewCompat.postInvalidateOnAnimation(this);
}
}
else
{
layoutChildView(true);
}
}
/**
*
关闭侧边栏mBackView,默认平滑关闭
*/
public
void
close()
{
close(true);
}
/**
*
关闭侧边栏mBackView
*
*
@param
isSmooth
是否平滑关闭
*/
public
void
close(boolean
isSmooth)
{
if
(isSmooth)
{
if
(mDragHelper.smoothSlideViewTo(mBackView,
mWidth,
0))
{
//动画在继续
ViewCompat.postInvalidateOnAnimation(this);
}
}
else
{
layoutChildView(false);
}
}
@Override
public
void
computeScroll()
{
puteScroll();
if
(mDragHelper.continueSettling(true))
{
//动画还在继续
ViewCompat.postInvalidateOnAnimation(this);
}
}
}<?xml
version="1.0"
encoding="utf-8"?>
<.csdn.blog.myswipelayout.view.SwipeLayout
xmlns:android="/apk/res/android"
android:id="@+id/sl"
android:layout_width="match_parent"
android:layout_height="60dp"
android:minHeight="60dp"
android:background="#44000000"
>
<!--后置布局-->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tv_call"
android:layout_width="60dp"
android:layout_height="match_parent"
android:background="#666666"
android:gravity="center"
android:text="Edit"
android:textColor="#ffffff"
/>
<TextView
android:id="@+id/tv_del"
android:layout_width="60dp"
android:layout_height="match_parent"
android:background="#ff0000"
android:gravity="center"
android:text="Delete"
android:textColor="#ffffff"
/>
</LinearLayout>
<!--前景布局-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#44ffffff"
android:gravity="center_vertical"
android:orientation="horizontal"
>
<ImageView
android:id="@+id/iv_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="15dp"
android:src="@drawable/head_1"
/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="Name"
/>
</LinearLayout>
</.csdn.blog.myswipelayout.view.SwipeLayout>/upload/information/20200623/125/126979.gif需要考虑2点:/**
*
侧拉SwipeLayout的监听
*
Created
by
mChenys
on
2015/12/26.
*/
public
interface
SwipeViewListener
{
//关闭
void
onClose(SwipeLayout
mSwipeLayout);
//打开
void
onOpen(SwipeLayout
mSwipeLayout);
//正在侧拉
void
onDraging(SwipeLayout
mSwipeLayout);
//开始要去关闭
void
onStartClose(SwipeLayout
mSwipeLayout);
//开始要去开启
void
onStartOpen(SwipeLayout
mSwipeLayout);
}//以下是定义SwipeLayout的打开,关闭,滑动的3种状态
public
enum
Status
{
CLOSE,
OPEN,
DRAGING;
}
//默认关闭
private
Status
mStatus
=
Status.CLOSE;
//滑动的监听器
private
SwipeViewListener
mSwipeViewListener;
//设置监听器
public
void
setSwipeViewListener(SwipeViewListener
swipeViewListener)
{
mSwipeViewListener
=
swipeViewListener;
}/**
*
处理滑动,打开,关闭的3种情况
*
在onViewPositionChanged
调用
*/
private
void
dispatchSwipeEvent()
{
if
(mSwipeViewListener
!=
null)
{
mSwipeViewListener.onDraging(this);
}
//记录上一次的状态
Status
preStatus
=
mStatus;
//获取当前的状态
mStatus
=
getCurrStatus();
if
(preStatus
!=
mStatus
&&
null
!=
mSwipeViewListener)
{
//说明有状态发生变化
if
(mStatus
==
Status.CLOSE)
{
//关闭
mSwipeViewListener.onClose(this);
}
else
if
(mStatus
==
Status.OPEN)
{
//打开
mSwipeViewListener.onOpen(this);
}
else
if
(mStatus
==
Status.DRAGING)
{
//这里有2中情况,要么要打开,要么要关闭
if
(preStatus
==
Status.CLOSE)
{
//如果之前是关闭的,那么就是要打开
mSwipeViewListener.onStartOpen(this);
}
else
if
(preStatus
==
Status.OPEN)
{
//如果之前是打开,那么就是要关闭
mSwipeViewListener.onStartClose(this);
}
}
}
}
/**
*
获取当前的状态
*
*
@return
*/
private
Status
getCurrStatus()
{
int
left
=
mFrontView.getLeft();
if
(left
==
0)
{
return
Status.CLOSE;
}
else
if
(left
==
-mRange)
{
return
Status.OPEN;
}
return
Status.DRAGING;
}public
class
MainActivity
extends
AppCompatActivity
{
private
List<String>
mData
=
new
ArrayList<>();//数据集合
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
//获取数据,注意:Arrays.asList返回的并不是一个java.util.ArrayList,而是一个Arrays类的内部类,该List实现是不能进行增删操作的
//因此必须再包装一下
mData
=
new
ArrayList<>(Arrays.asList(Constant.NAME));
ListView
listView
=
new
ListView(this);
listView.setAdapter(mAdapter);
setContentView(listView);
}
//自定义适配器
private
BaseAdapter
mAdapter
=
new
BaseAdapter()
{
//标记当前打开的SwipeLayout的集合
private
List<SwipeLayout>
mOpenItem
=
new
ArrayList<>();
@Override
public
int
getCount()
{
return
mData.size();
}
@Override
public
String
getItem(int
position)
{
return
mData.get(position);
}
@Override
public
long
getItemId(int
position)
{
return
position;
}
@Override
public
View
getView(final
int
position,
View
convertView,
ViewGroup
parent)
{
ViewHolder
holder
=
null;
if
(null
==
convertView)
{
holder
=
new
ViewHolder();
convertView
=
View.inflate(MainActivity.this,
R.layout.item_list,
null);
holder.mSwipeLayout
=
(SwipeLayout)
convertView;
holder.tvName
=
(TextView)
convertView.findViewById(R.id.tv_name);
holder.tvDel
=
(TextView)
convertView.findViewById(R.id.tv_del);
holder.tvEdit
=
(TextView)
convertView.findViewById(R.id.tv_edit);
convertView.setTag(holder);
}
else
{
holder
=
(ViewHolder)
convertView.getTag();
}
//设置侧拉监听
holder.mSwipeLayout.setSwipeViewListener(getSwipeViewListener());
holder.tvName.setText(getItem(position));
holder.tvDel.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
v)
{
//删除
mData.remove(position);
mAdapter.notifyDataSetChanged();
}
});
holder.tvEdit.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
v)
{
ToastUtils.showToast(MainActivity.this,"编辑");
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 通信行业5G通信技术研究与开发与实施方案
- 酒店行业合作经营合同书
- 电子行业智能制造生产线方案
- 智能家居安全与智能控制技术方案设计
- 三农产品电子商务数据采集与分析应用方案
- 工业制造智能化升级与管理系统开发方案
- 金融行业数字化供应链管理解决方案
- 区块链技术在知识产权保护中的应用方案
- 新公司财务工作计划范文(26篇)
- 电大社会实践调查报告6篇
- 数据安全事件的溯源与责任追究
- 2022课程方案试题
- 中国文化-古今长安(双语)智慧树知到期末考试答案章节答案2024年西安欧亚学院
- 苏教译林版五年级上学期英语第七单元Unit7《At weekends》测试卷(含答案解析)
- 丝氨酸蛋白酶在代谢性疾病中的作用
- 纪念与象征-空间中的实体艺术 课件-2023-2024学年高中美术人美版(2019)美术鉴赏
- 河北钢铁集团沙河中关铁矿有限公司矿山地质环境保护与土地复垦方案
- 《交通事故应急预案》课件
- 创伤急救理论知识考试试题及答案
- 创意营造学智慧树知到期末考试答案2024年
- (带附件)建筑工人劳务合同
评论
0/150
提交评论