Android UI效果实现——Activity滑动退出效果
更新说明:
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滑动退出效果的更多相关文章
- 【Android UI】案例03滑动切换效果的实现(ViewPager)
本例使用ViewPager实现滑动切换的效果.本例涉及的ViewPager.为android.support.v4.view.ViewPager.所以须要在android项目中导入android-su ...
- Android 动画之View动画效果和Activity切换动画效果
View动画效果: 1.>>Tween动画通过对View的内容进行一系列的图形变换(平移.缩放.旋转.透明度变换)实现动画效果,补间动画需要使用<set>节点作为根节点,子节点 ...
- Android 编程下实现 Activity 的透明效果
实现方式一(使用系统透明样式) 通过配置 Activity 的样式来实现,在 AndroidManifest.xml 找到要实现透明效果的 Activity,在 Activity 的配置中添加如下的代 ...
- ANDROID模拟火花粒子的滑动喷射效果
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 年前换了一个手机,SONY的Z3C.这个手机在解锁屏幕时有一个滑动动画,类似火 ...
- android中listview的item滑动删除效果(已解决listview点击问题)
领导看到iphone上tableview有个滑动删除的效果,要求在android上也实现,搜了下资料,实现起来比较简单,可弄到后面,居然不能点击了,把一篇文章中的代码修改了一下,捣鼓了一番,搞定,下面 ...
- android 总结(样式)—跑马灯 button的点击效果 RadioGroup 实现滑动的效果 button 下面有阴影 卡片样式
<Button android:layout_width="wrap_content" android:layout_height="wrap_content&qu ...
- Android UI设计
Android UI设计--PopupWindow显示位置设置 摘要: 当点击某个按钮并弹出PopupWindow时,PopupWindow左下角默认与按钮对齐,但是如果PopupWindow是下图的 ...
- Android 设定activity的进入和退出效果
看了android的源代码和资源文件,终于明白如何去修改设置Dialog和Activity的进入和退出效果了.设置Dialog首先通过 getWindow()方法获取它的窗口,然后通过getAttri ...
- Android UI - 实现广告Banner旋转木马效果
Android UI - 实现广告Banner旋转木马效果 前言 本篇博客要分享的一个效果是实现广告Banner轮播效果,这个效果也比較常见,一些视频类应用就常常有,就拿360影视大全来举例吧: 用红 ...
随机推荐
- android 自定义组合控件 顶部导航栏
在软件开发过程中,经常见到,就是APP 的标题栏样式几乎都是一样的,只是文字不同而已,两边图标不同.为了减少重复代码,提高效率, 方便大家使用,我们把标题栏通过组合的方式定义成一个控件. 例下图: 点 ...
- ASP.NET5 中静态文件的各种使用方式
所谓静态文件,包含HTML文件,css文件.图片文件和js文件等,他们是服务器直接读取到客户端的一些资源,在这篇文章中,我们将解释关于ASP.NET5和静态文件的一些内容. 服务端的静态文件 默认情况 ...
- windows 创建服务提示失败 5 拒绝 访问拒绝
1.桌面创建文本,输入 sc create .....echo. & pause 保存,重命名为 .bat 2.右键该文件,管理员运行
- 全局变量&局部变量
一.局部变量: 定义在函数内部的变量以及函数的形参成为局部变量 作用于:从定义那一行开始知道与其所在的代码块结束 生命周期:从程序运行到定义那一行开始分配存储空间到程序离开该变量所在的作用域 特点: ...
- 启动obiee
启动obiee:1.启动数据库第一步:打开Oracle监听$ lsnrctl start第二步:使用sysdab角色登录sqlplussqlplus / as sysdba第三步:启动数据库SQL&g ...
- Linux逻辑卷管理器(LVM)
LVM基础 通过使用Linux的逻辑卷管理器(Logical Volume Manager, LVM),用户可以在系统运行时动态调整文件系统的大小,把数据从一块硬盘重定位到另一块硬盘,也可以提高I/O ...
- 09_platform-tools简介&常见adb指令
SDK下面的文件夹说明add-ons 附加的附属的一些信息.docs Android开发的帮助文件.extras 支持的jar包,高版本兼容底版本.google usb的驱动.platforms 存放 ...
- http 301、304状态码
在利用httpwatch进行抓包分析时,我们经常会看到200.301.304这几个状态码.具本三者是什么意思呢? 200表示正常0k,这个是地球人都知道的了. 301 Moved Permanentl ...
- VC++2010下编译STLport,Boost
VC++2010下编译STLport,Boost 最近在想向Boost转移,努力掌握Boost代码的过程中, STLport版本:5.2.1 Boost版本:1.4.6.1 (1.4.7.0也OK) ...
- LINE最新版6.5.0在iOS上的删除信息取证
iOS: 9.3.2版 LINE: 6.5.0版 取出LINE的数据库 Line.sqlite,路径如下所示: 检视删除的信息,发现还有不少残留,虽然都是片段,但拼拼凑凑总还是能有些蛛丝马迹,毕竟,总 ...