今天还是给大家带来自定义控件的编写,自定义一个ListView的左右滑动删除Item的效果,这个效果之前已经实现过了,有兴趣的可以看下Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果,之前使用的是滑动类Scroller来实现的,但是看了下通知栏的左右滑动删除效果,确实很棒,当我们滑动Item超过一半的时候,item的透明度就变成了0,我们就知道抬起手指的时候item就被删除了,当item的透明度不为0的时候,我们抬起手指Item会回到起始位置,这样我们就知道拖动到什么位置item会删除,什么位置Item不删除,用户体验更好了,还有一个效果,就是我们滑动删除了item的时候,ListView的其他item会出现向上或者向下滚动的效果,感觉效果很棒,所以在GitHub上面搜索了下,发现很多开源库都有这个效果,比如ListViewAnimations, android-swipelistview等等,我看了下实现原理,使用的是Jake Wharton的动画开源库NineOldAndroids,这个库究竟是干嘛的呢?在API3.0(Honeycomb), SDK新增了一个android.animation包,里面的类是实现动画效果相关的类,通过Honeycomb API,能够实现非常复杂的动画效果,但是如果开发者想在3.0以下使用这一套API, 则需要使用开源框架Nine Old Androids,在这个库中会根据我们运行的机器判断其SDK版本,如果是API3.0以上则使用Android自带的动画类,否则就使用Nine Old Androids库中,这是一个兼容库,接下来我们就来看看这个效果的具体实现吧
实现该效果的主要思路
- 先根据手指触摸的点来获取点击的是ListView的哪一个Item
- 当手指在屏幕上面滑动的时候,我们要使得Item跟随手指的滑动而滑动
- 当我们抬起手指的时候,我们根据滑动的距离或者手指在屏幕上面的速度来判断Item是滑出屏幕还是滑动至其实位置
- Item滑出屏幕时,使ListView的其他item产生向上挤压或者向下挤压的效果
大致的思路这是这四步,其中的一些细节接下来我会一一为大家解答的,接下来我们就用代码来实现这种效果吧
首先我们新建一个工程,叫Swipedismisslistview,我们需要将Nine Old Androids这个库引入到工程,大家可以去https://github.com/JakeWharton/NineOldAndroids下载,可以使用Jar包,也可以使用工程库的形式引入到我们自己的工程,我们还需要自定义一个ListView,我们先看代码然后给大家讲解下具体的功能实现
- package com.example.swipedismisslistview;
- import static com.nineoldandroids.view.ViewHelper.setAlpha;
- import static com.nineoldandroids.view.ViewHelper.setTranslationX;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.VelocityTracker;
- import android.view.View;
- import android.view.ViewConfiguration;
- import android.view.ViewGroup;
- import android.widget.AdapterView;
- import android.widget.ListView;
- import com.nineoldandroids.animation.Animator;
- import com.nineoldandroids.animation.AnimatorListenerAdapter;
- import com.nineoldandroids.animation.ValueAnimator;
- import com.nineoldandroids.view.ViewHelper;
- import com.nineoldandroids.view.ViewPropertyAnimator;
- /**
- * @blog http://blog.csdn.net/xiaanming
- *
- * @author xiaanming
- *
- */
- public class SwipeDismissListView extends ListView {
- /**
- * 认为是用户滑动的最小距离
- */
- private int mSlop;
- /**
- * 滑动的最小速度
- */
- private int mMinFlingVelocity;
- /**
- * 滑动的最大速度
- */
- private int mMaxFlingVelocity;
- /**
- * 执行动画的时间
- */
- protected long mAnimationTime = 150;
- /**
- * 用来标记用户是否正在滑动中
- */
- private boolean mSwiping;
- /**
- * 滑动速度检测类
- */
- private VelocityTracker mVelocityTracker;
- /**
- * 手指按下的position
- */
- private int mDownPosition;
- /**
- * 按下的item对应的View
- */
- private View mDownView;
- private float mDownX;
- private float mDownY;
- /**
- * item的宽度
- */
- private int mViewWidth;
- /**
- * 当ListView的Item滑出界面回调的接口
- */
- private OnDismissCallback onDismissCallback;
- /**
- * 设置动画时间
- *
- * @param mAnimationTime
- */
- public void setmAnimationTime(long mAnimationTime) {
- this.mAnimationTime = mAnimationTime;
- }
- /**
- * 设置删除回调接口
- *
- * @param onDismissCallback
- */
- public void setOnDismissCallback(OnDismissCallback onDismissCallback) {
- this.onDismissCallback = onDismissCallback;
- }
- public SwipeDismissListView(Context context) {
- this(context, null);
- }
- public SwipeDismissListView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- public SwipeDismissListView(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- ViewConfiguration vc = ViewConfiguration.get(context);
- mSlop = vc.getScaledTouchSlop();
- mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 8; //获取滑动的最小速度
- mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity(); //获取滑动的最大速度
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- switch (ev.getAction()) {
- case MotionEvent.ACTION_DOWN:
- handleActionDown(ev);
- break;
- case MotionEvent.ACTION_MOVE:
- return handleActionMove(ev);
- case MotionEvent.ACTION_UP:
- handleActionUp(ev);
- break;
- }
- return super.onTouchEvent(ev);
- }
- /**
- * 按下事件处理
- *
- * @param ev
- * @return
- */
- private void handleActionDown(MotionEvent ev) {
- mDownX = ev.getX();
- mDownY = ev.getY();
- mDownPosition = pointToPosition((int) mDownX, (int) mDownY);
- if (mDownPosition == AdapterView.INVALID_POSITION) {
- return;
- }
- mDownView = getChildAt(mDownPosition - getFirstVisiblePosition());
- if (mDownView != null) {
- mViewWidth = mDownView.getWidth();
- }
- //加入速度检测
- mVelocityTracker = VelocityTracker.obtain();
- mVelocityTracker.addMovement(ev);
- }
- /**
- * 处理手指滑动的方法
- *
- * @param ev
- * @return
- */
- private boolean handleActionMove(MotionEvent ev) {
- if (mVelocityTracker == null || mDownView == null) {
- return super.onTouchEvent(ev);
- }
- // 获取X方向滑动的距离
- float deltaX = ev.getX() - mDownX;
- float deltaY = ev.getY() - mDownY;
- // X方向滑动的距离大于mSlop并且Y方向滑动的距离小于mSlop,表示可以滑动
- if (Math.abs(deltaX) > mSlop && Math.abs(deltaY)
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录