Android自定义View之仿知乎滑动删除Activity
2016-05-16 19:07
483 查看
先看下具体的实现效果:
上面图片里包含两种效果,一个是向右滑动删除Activity,这个大家可以参考夏神的文章/article/1645776.html
里面讲解很令人佩服,另一个是向上滑动删除Activity,这个有点类似平时手机的通知栏,滑动删除的知识点和思想基本也是一样的。
项目结构如下:
下面着重讲解如何实现向上滑动删除Activty的自定义View
具体代码如下:
上面就是是完成整个自定义view的过程,涉及到的知识点总结整理如下:
(1)Android视图坐标系的相对坐标和绝对坐标:
getX()与getRawX()的区别
getY()与getRawY()的区别
(2)mTouchSlop系统认为是滑动的最小距离
mTouchSlop=ViewConfiguration.get(context).getScaledTouchSlop();
(3)关于Scroller的滑动调用方法:
startScroll(int startX, int startY, int dx, int dy, int duration)
表示在duration时间内,从当前的(x,y)点滑动到(x+dx,y+dy)点。
scrollBy (int x, int y) 滑动的偏移量
scrollTo(int x, int y) 滑动到指定的坐标
getCurrX() 返回当前view的x偏移量
getCurrY() 返回当前view的y偏移量
(4)判断当前用户的操作是否是滑动状态:
if (Math.abs(moveY - downY) > mTouchSlop&& Math.abs(moveX - downX) < mTouchSlop) {
isSilding = true;
}
上面图片里包含两种效果,一个是向右滑动删除Activity,这个大家可以参考夏神的文章/article/1645776.html
里面讲解很令人佩服,另一个是向上滑动删除Activity,这个有点类似平时手机的通知栏,滑动删除的知识点和思想基本也是一样的。
项目结构如下:
下面着重讲解如何实现向上滑动删除Activty的自定义View
具体代码如下:
/** * 自定义滑动删除布局 */ public class SildingFinishLayoutVertical extends RelativeLayout implements OnTouchListener,GestureDetector.OnGestureListener { /** * SildingFinishLayout布局的父布局 */ private ViewGroup mParentView; /** * 处理滑动逻辑的View */ private View touchView; /** * 滑动的最小距离 */ private int mTouchSlop; /** * 按下点的X坐标 */ private int downX; /** * 按下点的Y坐标 */ private int downY; /** * 临时存储X坐标 */ private int tempX; /** * 临时存储Y坐标 */ private int tempY; /** * 滑动类 */ private Scroller mScroller; /** *SildingFinishLayout的宽度 */ private int viewWidth; /** *SildingFinishLayout的高度 */ private int viewHeight; /** * 记录是否正在滑动 */ private boolean isSilding; private OnSildingFinishListener onSildingFinishListener; private boolean isFinish; public SildingFinishLayoutVertical(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SildingFinishLayoutVertical(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mScroller = new Scroller(context); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed) { // 获取SildingFinishLayout所在布局的父布局 mParentView = (ViewGroup) this.getParent(); //mParentView.getBackground().setAlpha(1);加这行代码会崩溃 //注意getWidth()和getMeasuredWidth()的区别; viewWidth = this.getWidth(); viewHeight = this.getHeight();//获取布局view的高度 } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } /** * 设置OnSildingFinishListener, 在onSildingFinish()方法中finish Activity * * @param onSildingFinishListener */ public void setOnSildingFinishListener(OnSildingFinishListener onSildingFinishListener) { this.onSildingFinishListener = onSildingFinishListener; } /** * 设置Touch的View * * @param touchView */ public void setTouchView(View touchView) { this.touchView = touchView; touchView.setOnTouchListener(this); } public View getTouchView() { return touchView; } /** *滚动出界面--从左向右滑出 */ private void scrollRight() { final int delta = (viewWidth + mParentView.getScrollX()); //getScrollX()是当前view的顶部相对于坐标原点(也就是手机屏幕的左上角的水平偏移量) // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item mScroller.startScroll(mParentView.getScrollX(), 0, -delta + 1, 0, Math.abs(delta)); postInvalidate(); } /** *滚动出界面--从下向上滑出 */ private void scrollTop() { final int delta = (viewHeight + mParentView.getScrollY()); // 调用startScroll方法来设置一些滚动的参数,我们在computeScroll()方法中调用scrollTo来滚动item mScroller.startScroll(0,mParentView.getScrollY(), 0, delta - 1, Math.abs(delta)); postInvalidate(); } /** *滚动到起始位置--从右向左 */ private void scrollOrigin() { int delta = mParentView.getScrollX(); mScroller.startScroll(mParentView.getScrollX(), 0, -delta, 0,Math.abs(delta)); postInvalidate(); } /** *滚动到起始位置--从上向下 */ private void scrollOriginFromTop() { int delta = mParentView.getScrollY();//getScrollY是偏移量 无正负之分 mScroller.startScroll(0,mParentView.getScrollY(), 0,-delta, Math.abs(delta)); postInvalidate(); } /** * touch的View是否是AbsListView, 例如ListView, GridView等其子类 * * @return */ private boolean isTouchOnAbsListView() { return touchView instanceof AbsListView ? true : false; } /** * touch的view是否是ScrollView或者其子类 * * @return */ private boolean isTouchOnScrollView() { return touchView instanceof ScrollView ? true : false; } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downX = tempX = (int) event.getRawX(); downY = tempY = (int) event.getRawY(); break; case MotionEvent.ACTION_MOVE: int moveX = (int) event.getRawX(); int moveY = (int) event.getRawY(); int deltaX = tempX - moveX; int deltaY = tempY - moveY; tempX = moveX; tempY = moveY; //if (Math.abs(moveX - downX) > mTouchSlop&& Math.abs((int) event.getRawY() - downY) < mTouchSlop) { if (Math.abs(moveY - downY) > mTouchSlop&& Math.abs(moveX - downX) < mTouchSlop) { isSilding = true; // 若touchView是AbsListView, // 则当手指滑动,取消item的点击事件,不然我们滑动也伴随着item点击事件的发生 if (isTouchOnAbsListView()) { MotionEvent cancelEvent = MotionEvent.obtain(event); cancelEvent .setAction(MotionEvent.ACTION_CANCEL | (event.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT)); v.onTouchEvent(cancelEvent); } } //if (moveX - downX >= 0 && isSilding) { if (moveY - downY <= 0 && isSilding) { //mParentView.scrollBy(deltaX, 0); mParentView.scrollBy(0, deltaY); // 屏蔽在滑动过程中ListView ScrollView等自己的滑动事件 if (isTouchOnScrollView() || isTouchOnAbsListView()) { return true; } } break; case MotionEvent.ACTION_UP: isSilding = false; // if (mParentView.getScrollX() <= -viewWidth / 2) { if (Math.abs(mParentView.getScrollY())>= viewHeight /2) { isFinish = true; // scrollRight(); scrollTop(); } else { // scrollOrigin(); scrollOriginFromTop(); isFinish = false; } break; } // 假如touch的view是AbsListView或者ScrollView 我们处理完上面自己的逻辑之后 // 再交给AbsListView, ScrollView自己处理其自己的逻辑 if (isTouchOnScrollView() || isTouchOnAbsListView()) { return v.onTouchEvent(event); } // 其他的情况直接返回true return true; } @Override public void computeScroll() { // 调用startScroll的时候scroller.computeScrollOffset()返回true,//Scroller.computeScrollOffset()方法是判断scroller的移动动画是否完成 if (mScroller.computeScrollOffset()) { mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); //if (mScroller.isFinished()) { if (true) { if (onSildingFinishListener != null && isFinish) { onSildingFinishListener.onSildingFinish(); } } } } /**GestureDetector.OnGestureListener start**/ @Override public boolean onDown(MotionEvent motionEvent) { return false; } @Override public void onShowPress(MotionEvent motionEvent) { } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return false; } @Override public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { return false; } @Override public void onLongPress(MotionEvent motionEvent) { } @Override public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { return false; } /**GestureDetector.OnGestureListener end**/ public interface OnSildingFinishListener { void onSildingFinish(); } }
上面就是是完成整个自定义view的过程,涉及到的知识点总结整理如下:
(1)Android视图坐标系的相对坐标和绝对坐标:
getX()与getRawX()的区别
getY()与getRawY()的区别
(2)mTouchSlop系统认为是滑动的最小距离
mTouchSlop=ViewConfiguration.get(context).getScaledTouchSlop();
(3)关于Scroller的滑动调用方法:
startScroll(int startX, int startY, int dx, int dy, int duration)
表示在duration时间内,从当前的(x,y)点滑动到(x+dx,y+dy)点。
scrollBy (int x, int y) 滑动的偏移量
scrollTo(int x, int y) 滑动到指定的坐标
getCurrX() 返回当前view的x偏移量
getCurrY() 返回当前view的y偏移量
(4)判断当前用户的操作是否是滑动状态:
if (Math.abs(moveY - downY) > mTouchSlop&& Math.abs(moveX - downX) < mTouchSlop) {
isSilding = true;
}
[完成DEMO下载]
(http://download.csdn.net/detail/happy_horse/9521978)相关文章推荐
- android imageButton 点击按钮前中后,按钮颜色的变化
- 国内下载android源码镜像地址及方法
- Android 热补丁动态修复框架小结
- Android学习——Menu
- 初始Volley框架 ImageLoader请求Url 并加载
- android animation——view进入退出动画
- Android学习——Dialog
- AndroidStudio目录结构视图解说,androidstudio视图
- Android屏幕适配方案(个人觉得不错,比percent-support-lib好用)
- setContentView()与LayoutInflater.from()的区别-android
- 史上最全的Android ViewDragHelper解析
- 从头学android_短信发送器
- Android dex分包方案
- android的消息处理机制——Looper,Handler,Message
- Android 源码编译相关
- Android必知必会-自定义Scrollbar样式
- Android必知必会-自定义Scrollbar样式
- Android文件系统深入剖析
- 怎样使一个Android应用不被杀死?
- Android设备测试应用总结