Android UI效果实现——Activity滑动退出效果
2014-07-10 05:55
260 查看
更新说明:
1、在QQ网友北京-旭的提醒下,在SlideFrame的initilize方法中添加了focusable、focusableInTouch、clickable的状态设置,否则会导致部分情况下无法滑动,感谢!
一、使用说明
使用方法很简单,只有一个类HorizontalActivity,继承自FragmentActivity类,实现了contentView的滑动事件触发和动画效果,要在自己的代码里实现,方法两种:
1、如果对Activity没特殊要求,直接继承HorizontalActivity即可
2、如果Activity的父类必须是某一特定类型的Activity子类,则可以仿照我的写法对该类进行继承
二、HorizontalActivity类的代码
三、使用详细步骤
1、建立一个Android工程,项目最小api level必须在api level 11及以上
2、把本类考入任意代码包下
3、项目中想要实现Activity滑动退出效果的Activity继承本类
4、如果要在滑动过程中显示上一个Activity的话,将Activity的背景设置为透明,方法建议通过设置Activity的Style或者说theme来实现
5、如果滑动过程中需要加入一些特殊效果,可以复写slideTo(int)方法,记得别把super.slideTo(int)给漏了,否则滑动失效
6、如果滑动结束后不希望立即返回上一页,可以复写onSlideFinish()方法
四、某项目中使用的效果展示
PS、
很简单的实现方法,但离我觉得完美还太远,所以如果有更好的实现方法希望可以一起交流下:
联系方式QQ:811868948,备注加上Android交流,有好的想法一定要联系我,谢谢!
联系方式E-Mail:halfmanhuang@gmail.com
1、在QQ网友北京-旭的提醒下,在SlideFrame的initilize方法中添加了focusable、focusableInTouch、clickable的状态设置,否则会导致部分情况下无法滑动,感谢!
一、使用说明
使用方法很简单,只有一个类HorizontalActivity,继承自FragmentActivity类,实现了contentView的滑动事件触发和动画效果,要在自己的代码里实现,方法两种:
1、如果对Activity没特殊要求,直接继承HorizontalActivity即可
2、如果Activity的父类必须是某一特定类型的Activity子类,则可以仿照我的写法对该类进行继承
二、HorizontalActivity类的代码
package com.beifeng.widget; import android.content.Context; import android.support.v4.app.FragmentActivity; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.DecelerateInterpolator; import android.view.animation.Transformation; import android.widget.FrameLayout; /** * HorizontalActivity:可滑动Activity * * 注意事项: 本Activity中与滑动方向相同的滑动操作会被拦截 * * @author HalfmanG2 * @version 1.0.0 * @since JDK7 SDK19 */ public class HorizontalActivity extends FragmentActivity { /** 框架视图 */ protected SlideFrame frameView; /** 内容视图 */ protected View contentView; @Override public void setContentView(int layoutResID) { // 初始化frame if (frameView == null) { // 未初始化则初始化 frameView = new SlideFrame(this); } else { // 已经初始化则清空 frameView.removeAllViews(); } // 创造framelayout的填充参数 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-1, -1); // 获取layoutResId对应的contentView视图并插入frameView LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); contentView = inflater.inflate(layoutResID, null); frameView.addView(contentView, params); // 设置frameview为根视图 super.setContentView(frameView); } @Override public void setContentView(View view) { // 初始化frame if (frameView == null) { // 未初始化则初始化 frameView = new SlideFrame(this); } else { // 已经初始化则清空 frameView.removeAllViews(); } // 创造framelayout的填充参数 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-1, -1); // 获取view为contentView视图并插入frameView contentView = view; frameView.addView(contentView, params); // 设置frameview为根视图 super.setContentView(frameView); } @Override public void setContentView(View view, LayoutParams params) { // 初始化frame if (frameView == null) { // 未初始化则初始化 frameView = new SlideFrame(this); } else { // 已经初始化则清空 frameView.removeAllViews(); } // 创造framelayout的填充参数 FrameLayout.LayoutParams fp = new FrameLayout.LayoutParams(-1, -1); // 获取view为contentView视图并插入frameView contentView = view; frameView.addView(contentView, fp); // 设置frameview为根视图 super.setContentView(frameView, params); } /** * 推出页面 */ protected void onSlideFinish() { finish(); } /** * 位移内容视图到 * * @param position * 目标位置 */ public void slideTo(int position) { if (android.os.Build.VERSION.SDK_INT > 10) { contentView.setX(position); } else { android.widget.FrameLayout.LayoutParams params = (android.widget.FrameLayout.LayoutParams) contentView .getLayoutParams(); params.setMargins(position, 0, -position, 0); contentView.setLayoutParams(params); } } /** * 获得当前容器位移 * * @return 当前容器位移 */ public int getSlide() { if (android.os.Build.VERSION.SDK_INT > 10) { return (int) contentView.getX(); } else { return ((android.widget.FrameLayout.LayoutParams) contentView .getLayoutParams()).leftMargin; } } /** * 滑动框架 * * @author HalfmanG2 * @version 1.0.0 * @since JDK7 SDK19 */ public class SlideFrame extends FrameLayout { /** 默认滑动阀值 */ private final static int DEFAULT_SLIDE_DUMPING = 8; /** 默认状态改变阀值 */ private final static int DEFAULT_DO_DUMPING = 100; /** 滑动起始位置与当前位置 */ private int startX, currentX, startY, currentY; /** 是否拦截事件,是否已经完成滑动检查 */ private boolean doNotIntercept, hasChecked; /** 滑动阀值 */ private int slideDumping; /** 操作阀值 */ private int doDumping; /** 滑屏动画 */ protected SlideAnimation slideAnimation; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { super.onInterceptTouchEvent(ev); // 若当前处在侧滑状态中,则拦截信号 if ((!doNotIntercept) && hasChecked) { return true; } // 否则使用默认 return false; } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { // 获得起始滑动坐标 startX = (int) ev.getX(); startY = (int) ev.getY(); // 初始化状态 doNotIntercept = false; hasChecked = false; } else if (!doNotIntercept) { // 获得当前滑动坐标 currentX = (int) ev.getX(); currentY = (int) ev.getY(); // 根据滑动类型区分 switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: // 移动状态 if (hasChecked) { doSlide(); } else { doCheck(); } break; case MotionEvent.ACTION_CANCEL: // 取消状态 case MotionEvent.ACTION_UP: // 抬起状态 // 初始化状态 doNotIntercept = false; hasChecked = false; if (Math.abs(currentX - startX) > doDumping) { if (currentX > startX) { // 右滑 slideAnimation = new SlideAnimation(getSlide(), contentView.getWidth(), 0); slideAnimation .setAnimationListener(new AnimationListener() { @Override public void onAnimationStart( Animation animation) { } @Override public void onAnimationRepeat( Animation animation) { } @Override public void onAnimationEnd( Animation animation) { onSlideFinish(); } }); startAnimation(slideAnimation); } } else { // 返回0位置 slideAnimation = new SlideAnimation(getSlide(), 0, 0); startAnimation(slideAnimation); } break; default: break; } } return super.dispatchTouchEvent(ev); } /** * 检查是否超过滑动阀值开启滑动状态 */ private void doCheck() { if (Math.abs(startY - currentY) > slideDumping) { hasChecked = true; doNotIntercept = true; slideTo(0); } else if (currentX - startX > slideDumping) { hasChecked = true; doNotIntercept = false; } } /** * 进行滑动 */ private void doSlide() { if (currentX > startX) { slideTo(currentX - startX); } else { slideTo(0); } } /** * 设置滑动阀值 * * @param dpValue */ public void setSlideDumping(int dpValue) { slideDumping = dip2px(dpValue); } /** * 设置状态改变阀值 * * @param dpValue */ public void setDoDumping(int dpValue) { doDumping = dip2px(dpValue); } /** * 二级构造方法 */ private void initilize() { setSlideDumping(DEFAULT_SLIDE_DUMPING); setDoDumping(DEFAULT_DO_DUMPING); doNotIntercept = false; hasChecked = false; setClickable(true); setFocusable(true); setFocusableInTouchMode(true); } /** * 构造方法 * * @param context * @param attrs * @param defStyle */ public SlideFrame(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initilize(); } /** * 构造方法 * * @param context * @param attrs */ public SlideFrame(Context context, AttributeSet attrs) { super(context, attrs); initilize(); } /** * 构造方法 * * @param context */ public SlideFrame(Context context) { super(context); initilize(); } /** * 讲dip值转换为px值,像素密度距离转像素距离 * * @param dipValue dp值 * @return px值 */ private int dip2px(float dipValue) { // 获得像素密度 final float scale = getContext().getResources().getDisplayMetrics().density; // 四舍五入dp值乘像素密度 return (int) (dipValue * scale + 0.5f); } } /** * 滑动动画类 * * @author HalfmanG2 */ public class SlideAnimation extends Animation { /** 起始位置,目标位置 */ private float from, to; /** * 构造方法 * @param from 起始位置 * @param to 目标位置 * @param startOffset 起始延迟 */ public SlideAnimation(int from, int to, int startOffset) { this.from = from; this.to = to; setFillEnabled(false); setDuration(200); setRepeatCount(0); setStartOffset(startOffset); setInterpolator(new DecelerateInterpolator()); } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { float current = from + (to - from) * interpolatedTime; slideTo((int) current); super.applyTransformation(interpolatedTime, t); } } }
三、使用详细步骤
1、建立一个Android工程,项目最小api level必须在api level 11及以上
2、把本类考入任意代码包下
3、项目中想要实现Activity滑动退出效果的Activity继承本类
4、如果要在滑动过程中显示上一个Activity的话,将Activity的背景设置为透明,方法建议通过设置Activity的Style或者说theme来实现
5、如果滑动过程中需要加入一些特殊效果,可以复写slideTo(int)方法,记得别把super.slideTo(int)给漏了,否则滑动失效
6、如果滑动结束后不希望立即返回上一页,可以复写onSlideFinish()方法
四、某项目中使用的效果展示
PS、
很简单的实现方法,但离我觉得完美还太远,所以如果有更好的实现方法希望可以一起交流下:
联系方式QQ:811868948,备注加上Android交流,有好的想法一定要联系我,谢谢!
联系方式E-Mail:halfmanhuang@gmail.com
相关文章推荐
- Android UI效果实现——Activity滑动退出效果
- 简单实现Activity退出时向下滑动退出的效果
- Activity手势滑动返回前一个Activity效果实现
- 手势滑动Activity之常见效果-- Slide,阴影效果与动画实现
- 使用SwipeBackLayout实现滑动退出页面的效果
- 实现Android 滑动退出Activity的功能
- android 两个activity实现切换时的滑动效果实现
- activity实现滑动效果
- SwipeBack实现Activity右滑退出(仿IOS效果)(学习:纯净日报第一弹)
- Android实现IOS向右滑动退出当前Activity
- Android 左右滑动切换页面或Activity的效果实现
- Activity随手势滑动退出,及模糊Dialog(类似于IOS的效果)
- 滑动结束 Activity(二)阴影效果和动画的实现
- 手势检测实现相册的左右滑动(并加上移动与旋转的特效) 首先,activity_main.xml里,使用ViewFlipper组件(可使用动画控制多个组件之间的切换效果) <?xml version="
- 如何实现Activity退出到桌面时的动画效果
- 滑动结束 Activity(二)阴影效果和动画的实现
- android使用ViewPager实现底部菜单栏和左右滑动效果,加载多个Activity
- 实现Activity的滑动返回效果(二)
- 实现 滑动退出 Fragment + Activity 二合一
- 实现Activity的滑动返回效果