本文主要是介绍安卓-Android实现右侧划出划入activity,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原帖: link
更新说明:
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:可滑动Activity18 * 19 * 注意事项: 本Activity中与滑动方向相同的滑动操作会被拦截20 * 21 * @author HalfmanG222 * @version 1.0.023 * @since JDK7 SDK1924 */25 public class HorizontalActivity extends FragmentActivity {26 27 /** 框架视图 */28 protected SlideFrame frameView;29 /** 内容视图 */30 protected View contentView;31 32 @Override33 public void setContentView(int layoutResID) {34 // 初始化frame35 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视图并插入frameView45 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 @Override53 public void setContentView(View view) {54 // 初始化frame55 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视图并插入frameView65 contentView = view;66 frameView.addView(contentView, params);67 // 设置frameview为根视图68 super.setContentView(frameView);69 }70 71 @Override72 public void setContentView(View view, LayoutParams params) {73 // 初始化frame74 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视图并插入frameView84 contentView = view;85 frameView.addView(contentView, fp);86 // 设置frameview为根视图87 super.setContentView(frameView, params);88 }89 90 /**91 * 推出页面92 */93 protected void onSlideFinish() {94 finish();95 }96 97 /**98 * 位移内容视图到99 * 100 * @param position 101 * 目标位置 102 */ 103 public 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) contentView 108 .getLayoutParams(); 109 params.setMargins(position, 0, -position, 0); 110 contentView.setLayoutParams(params); 111 } 112 } 113 114 /** 115 * 获得当前容器位移 116 * 117 * @return 当前容器位移 118 */ 119 public int getSlide() { 120 if (android.os.Build.VERSION.SDK_INT > 10) { 121 return (int) contentView.getX(); 122 } else { 123 return ((android.widget.FrameLayout.LayoutParams) contentView 124 .getLayoutParams()).leftMargin; 125 } 126 } 127 128 /** 129 * 滑动框架 130 * 131 * @author HalfmanG2 132 * @version 1.0.0 133 * @since JDK7 SDK19 134 */ 135 public 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 @Override 152 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 @Override 163 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) { 179 doSlide(); 180 } else { 181 doCheck(); 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) { 190 if (currentX > startX) { 191 // 右滑 192 slideAnimation = new SlideAnimation(getSlide(), 193 contentView.getWidth(), 0); 194 slideAnimation 195 .setAnimationListener(new AnimationListener() { 196 @Override 197 public void onAnimationStart( 198 Animation animation) { 199 } 200 201 @Override 202 public void onAnimationRepeat( 203 Animation animation) { 204 } 205 206 @Override 207 public void onAnimationEnd( 208 Animation animation) { 209 onSlideFinish(); 210 } 211 }); 212 startAnimation(slideAnimation); 213 } 214 } else { 215 // 返回0位置 216 slideAnimation = new SlideAnimation(getSlide(), 0, 0); 217 startAnimation(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 dpValue 256 */ 257 public void setSlideDumping(int dpValue) { 258 slideDumping = dip2px(dpValue); 259 } 260 261 /** 262 * 设置状态改变阀值 263 * 264 * @param dpValue 265 */ 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 context 287 * @param attrs 288 * @param defStyle 289 */ 290 public SlideFrame(Context context, AttributeSet attrs, int defStyle) { 291 super(context, attrs, defStyle); 292 initilize(); 293 } 294 295 /** 296 * 构造方法 297 * 298 * @param context 299 * @param attrs 300 */ 301 public SlideFrame(Context context, AttributeSet attrs) { 302 super(context, attrs); 303 initilize(); 304 } 305 306 /** 307 * 构造方法 308 * 309 * @param context 310 */ 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 HalfmanG2 334 */ 335 public 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 @Override 354 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@gmail.com
<div id="blog_post_info">
<div class="clear"></div>
<div id="post_next_prev"><br>
<a href="https://www.cnblogs.com/halfmanhuang/p/3837261.html" class="p_n_p_prefix">» </a> 下一篇: <a href="https://www.cnblogs.com/halfmanhuang/p/3837261.html" title="发布于 2014-07-11 11:00">Android UI效果实现——滑动模糊渐变效果实现</a>
这篇关于安卓-Android实现右侧划出划入activity的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!