失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android UI效果实现——Activity滑动退出效果

Android UI效果实现——Activity滑动退出效果

时间:2022-12-18 21:46:09

相关推荐

Android UI效果实现——Activity滑动退出效果

更新说明:

1、在QQ网友北京-旭的提醒下,在SlideFrame的initilize方法中添加了focusable、focusableInTouch、clickable的状态设置,否则会导致部分情况下无法滑动,感谢!

一、效果动图

二、使用说明

使用方法很简单,只有一个类HorizontalActivity,继承自FragmentActivity类,实现了contentView的滑动事件触发和动画效果,要在自己的代码里实现,方法两种:

1、如果对Activity没特殊要求,直接继承HorizontalActivity即可

2、如果Activity的父类必须是某一特定类型的Activity子类,则可以仿照我的写法对该类进行继承

三、HorizontalActivity类的代码

1 package com.beifeng.widget; 2 3 import android.content.Context; 4 import android.support.v4.app.FragmentActivity; 5 import android.util.AttributeSet; 6 import android.view.LayoutInflater; 7 import android.view.MotionEvent; 8 import android.view.View; 9 import android.view.ViewGroup.LayoutParams; 10 import android.view.animation.Animation; 11 import android.view.animation.Animation.AnimationListener; 12 import android.view.animation.DecelerateInterpolator; 13 import android.view.animation.Transformation; 14 import android.widget.FrameLayout; 15 16 /** 17 * HorizontalActivity:可滑动Activity 18 * 19 * 注意事项: 本Activity中与滑动方向相同的滑动操作会被拦截 20 * 21 * @author HalfmanG2 22 * @version 1.0.0 23 * @since JDK7 SDK19 24 */ 25 public class HorizontalActivity extends FragmentActivity { 26 27/** 框架视图 */ 28protected SlideFrame frameView; 29/** 内容视图 */ 30protected View contentView; 31 32@Override 33public void setContentView(int layoutResID) { 34 // 初始化frame 35 if (frameView == null) { 36 // 未初始化则初始化 37 frameView = new SlideFrame(this); 38 } else { 39 // 已经初始化则清空 40 frameView.removeAllViews(); 41 } 42 // 创造framelayout的填充参数 43 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-1, -1); 44 // 获取layoutResId对应的contentView视图并插入frameView 45 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 46 contentView = inflater.inflate(layoutResID, null); 47 frameView.addView(contentView, params); 48 // 设置frameview为根视图 49 super.setContentView(frameView); 50} 51 52@Override 53public void setContentView(View view) { 54 // 初始化frame 55 if (frameView == null) { 56 // 未初始化则初始化 57 frameView = new SlideFrame(this); 58 } else { 59 // 已经初始化则清空 60 frameView.removeAllViews(); 61 } 62 // 创造framelayout的填充参数 63 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(-1, -1); 64 // 获取view为contentView视图并插入frameView 65 contentView = view; 66 frameView.addView(contentView, params); 67 // 设置frameview为根视图 68 super.setContentView(frameView); 69} 70 71@Override 72public void setContentView(View view, LayoutParams params) { 73 // 初始化frame 74 if (frameView == null) { 75 // 未初始化则初始化 76 frameView = new SlideFrame(this); 77 } else { 78 // 已经初始化则清空 79 frameView.removeAllViews(); 80 } 81 // 创造framelayout的填充参数 82 FrameLayout.LayoutParams fp = new FrameLayout.LayoutParams(-1, -1); 83 // 获取view为contentView视图并插入frameView 84 contentView = view; 85 frameView.addView(contentView, fp); 86 // 设置frameview为根视图 87 super.setContentView(frameView, params); 88} 89 90/** 91* 推出页面 92*/ 93protected void onSlideFinish() { 94 finish(); 95} 96 97/** 98* 位移内容视图到 99* 100* @param position101* 目标位置102*/103public void slideTo(int position) {104 if (android.os.Build.VERSION.SDK_INT > 10) {105 contentView.setX(position);106 } else {107 android.widget.FrameLayout.LayoutParams params = (android.widget.FrameLayout.LayoutParams) contentView108 .getLayoutParams();109 params.setMargins(position, 0, -position, 0);110 contentView.setLayoutParams(params);111 }112}113 114/**115* 获得当前容器位移116* 117* @return 当前容器位移118*/119public int getSlide() {120 if (android.os.Build.VERSION.SDK_INT > 10) {121 return (int) contentView.getX();122 } else {123 return ((android.widget.FrameLayout.LayoutParams) contentView124 .getLayoutParams()).leftMargin;125 }126}127 128/**129* 滑动框架130* 131* @author HalfmanG2132* @version 1.0.0133* @since JDK7 SDK19134*/135public class SlideFrame extends FrameLayout {136 /** 默认滑动阀值 */137 private final static int DEFAULT_SLIDE_DUMPING = 8;138 /** 默认状态改变阀值 */139 private final static int DEFAULT_DO_DUMPING = 100;140 /** 滑动起始位置与当前位置 */141 private int startX, currentX, startY, currentY;142 /** 是否拦截事件,是否已经完成滑动检查 */143 private boolean doNotIntercept, hasChecked;144 /** 滑动阀值 */145 private int slideDumping;146 /** 操作阀值 */147 private int doDumping;148 /** 滑屏动画 */149 protected SlideAnimation slideAnimation;150 151 @Override152 public boolean onInterceptTouchEvent(MotionEvent ev) {153 super.onInterceptTouchEvent(ev);154 // 若当前处在侧滑状态中,则拦截信号155 if ((!doNotIntercept) && hasChecked) {156 return true;157 }158 // 否则使用默认159 return false;160 }161 162 @Override163 public boolean dispatchTouchEvent(MotionEvent ev) {164 if (ev.getAction() == MotionEvent.ACTION_DOWN) {165 // 获得起始滑动坐标166 startX = (int) ev.getX();167 startY = (int) ev.getY();168 // 初始化状态169 doNotIntercept = false;170 hasChecked = false;171 } else if (!doNotIntercept) {172 // 获得当前滑动坐标173 currentX = (int) ev.getX();174 currentY = (int) ev.getY();175 // 根据滑动类型区分176 switch (ev.getAction()) {177 case MotionEvent.ACTION_MOVE: // 移动状态178 if (hasChecked) {179doSlide();180 } else {181doCheck();182 }183 break;184 case MotionEvent.ACTION_CANCEL: // 取消状态185 case MotionEvent.ACTION_UP: // 抬起状态186 // 初始化状态187 doNotIntercept = false;188 hasChecked = false;189 if (Math.abs(currentX - startX) > doDumping) {190if (currentX > startX) {191 // 右滑192 slideAnimation = new SlideAnimation(getSlide(),193 contentView.getWidth(), 0);194 slideAnimation195 .setAnimationListener(new AnimationListener() {196 @Override197 public void onAnimationStart(198 Animation animation) {199 }200 201 @Override202 public void onAnimationRepeat(203 Animation animation) {204 }205 206 @Override207 public void onAnimationEnd(208 Animation animation) {209onSlideFinish();210 }211 });212 startAnimation(slideAnimation);213}214 } else {215// 返回0位置216slideAnimation = new SlideAnimation(getSlide(), 0, 0);217startAnimation(slideAnimation);218 }219 break;220 default:221 break;222 }223 }224 return super.dispatchTouchEvent(ev);225 }226 227 /**228* 检查是否超过滑动阀值开启滑动状态229*/230 private void doCheck() {231 if (Math.abs(startY - currentY) > slideDumping) {232 hasChecked = true;233 doNotIntercept = true;234 slideTo(0);235 } else if (currentX - startX > slideDumping) {236 hasChecked = true;237 doNotIntercept = false;238 }239 }240 241 /**242* 进行滑动243*/244 private void doSlide() {245 if (currentX > startX) {246 slideTo(currentX - startX);247 } else {248 slideTo(0);249 }250 }251 252 /**253* 设置滑动阀值254* 255* @param dpValue256*/257 public void setSlideDumping(int dpValue) {258 slideDumping = dip2px(dpValue);259 }260 261 /**262* 设置状态改变阀值263* 264* @param dpValue265*/266 public void setDoDumping(int dpValue) {267 doDumping = dip2px(dpValue);268 }269 270 /**271* 二级构造方法272*/273 private void initilize() {274 setSlideDumping(DEFAULT_SLIDE_DUMPING);275 setDoDumping(DEFAULT_DO_DUMPING);276 doNotIntercept = false;277 hasChecked = false;278 setClickable(true);279 setFocusable(true);280 setFocusableInTouchMode(true);281 }282 283 /**284* 构造方法285* 286* @param context287* @param attrs288* @param defStyle289*/290 public SlideFrame(Context context, AttributeSet attrs, int defStyle) {291 super(context, attrs, defStyle);292 initilize();293 }294 295 /**296* 构造方法297* 298* @param context299* @param attrs300*/301 public SlideFrame(Context context, AttributeSet attrs) {302 super(context, attrs);303 initilize();304 }305 306 /**307* 构造方法308* 309* @param context310*/311 public SlideFrame(Context context) {312 super(context);313 initilize();314 }315 316 /**317* 讲dip值转换为px值,像素密度距离转像素距离318* 319* @param dipValue dp值320* @return px值321*/322 private int dip2px(float dipValue) {323 // 获得像素密度324 final float scale = getContext().getResources().getDisplayMetrics().density;325 // 四舍五入dp值乘像素密度326 return (int) (dipValue * scale + 0.5f);327 }328}329 330/**331* 滑动动画类332* 333* @author HalfmanG2334*/335public class SlideAnimation extends Animation {336 /** 起始位置,目标位置 */337 private float from, to;338 /**339* 构造方法340* @param from 起始位置341* @param to 目标位置342* @param startOffset 起始延迟343*/344 public SlideAnimation(int from, int to, int startOffset) {345 this.from = from;346 this.to = to;347 setFillEnabled(false);348 setDuration(200);349 setRepeatCount(0);350 setStartOffset(startOffset);351 setInterpolator(new DecelerateInterpolator());352 }353 @Override354 protected void applyTransformation(float interpolatedTime,355 Transformation t) {356 float current = from + (to - from) * interpolatedTime;357 slideTo((int) current);358 super.applyTransformation(interpolatedTime, t);359 }360}361 }

四、使用详细步骤

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@

如果觉得《Android UI效果实现——Activity滑动退出效果》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。