这里有新鲜出炉的精品教程,程序狗速度看过来!
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。
最近做项目遇到这样的需求,要做条目条目拖拽删除效果,实际效果和QQ消息删除一样,侧滑有制定和删除,下面通过本文给大家分享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条目拖拽删除功能实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHPERZ网站的支持!
来源: http://www.phperz.com/article/17/0914/345847.html