更新说明:

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滑动退出效果的更多相关文章

  1. 【Android UI】案例03滑动切换效果的实现(ViewPager)

    本例使用ViewPager实现滑动切换的效果.本例涉及的ViewPager.为android.support.v4.view.ViewPager.所以须要在android项目中导入android-su ...

  2. Android 动画之View动画效果和Activity切换动画效果

    View动画效果: 1.>>Tween动画通过对View的内容进行一系列的图形变换(平移.缩放.旋转.透明度变换)实现动画效果,补间动画需要使用<set>节点作为根节点,子节点 ...

  3. Android 编程下实现 Activity 的透明效果

    实现方式一(使用系统透明样式) 通过配置 Activity 的样式来实现,在 AndroidManifest.xml 找到要实现透明效果的 Activity,在 Activity 的配置中添加如下的代 ...

  4. ANDROID模拟火花粒子的滑动喷射效果

    转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 年前换了一个手机,SONY的Z3C.这个手机在解锁屏幕时有一个滑动动画,类似火 ...

  5. android中listview的item滑动删除效果(已解决listview点击问题)

    领导看到iphone上tableview有个滑动删除的效果,要求在android上也实现,搜了下资料,实现起来比较简单,可弄到后面,居然不能点击了,把一篇文章中的代码修改了一下,捣鼓了一番,搞定,下面 ...

  6. android 总结(样式)—跑马灯 button的点击效果 RadioGroup 实现滑动的效果 button 下面有阴影 卡片样式

    <Button android:layout_width="wrap_content" android:layout_height="wrap_content&qu ...

  7. Android UI设计

    Android UI设计--PopupWindow显示位置设置 摘要: 当点击某个按钮并弹出PopupWindow时,PopupWindow左下角默认与按钮对齐,但是如果PopupWindow是下图的 ...

  8. Android 设定activity的进入和退出效果

    看了android的源代码和资源文件,终于明白如何去修改设置Dialog和Activity的进入和退出效果了.设置Dialog首先通过 getWindow()方法获取它的窗口,然后通过getAttri ...

  9. Android UI - 实现广告Banner旋转木马效果

    Android UI - 实现广告Banner旋转木马效果 前言 本篇博客要分享的一个效果是实现广告Banner轮播效果,这个效果也比較常见,一些视频类应用就常常有,就拿360影视大全来举例吧: 用红 ...

随机推荐

  1. Android的消息处理机制,handler,message,looper(一)

    当应用程序启动时,Android首先会开启一个主线程(也就是UI线程),主线程为管理界面中的UI控件.在程序开发时,对于比较耗时的操作,通常会为其开辟一个单独的线程来执行,以尽可能减少用户的等待时间. ...

  2. 初探appium之环境搭建

    前段时间一直在折腾python的爬虫,想搞接口自动化.但是写了一个月,发现在我现在的这份的工作中根本接触不到接口.所以就想先放下来,先做点目前能够接触到的,也需要做的东西. 东西越来越多,人手不足.自 ...

  3. python学习笔记(递归函数)

    博主看了看递归.说的简单点就是程序里面再调用程序本身,或者是方法里面再调研方法本身.或者是函数里面再调研函数本身 用于什么场景呢,博主这里是父子节点排序,父子节点的查询 直接上代码: #!/usr/b ...

  4. C语言之实现控制台光标随意移动

    原理引入windows.h,首先是要获得输入的东西,然后通过判断: 1.方向键:执行上下左右的移动功能 2:回车键:执行换行的功能. 3.普通键:输入功能. 终点就是要获取到屏幕上的坐标,当按下了方向 ...

  5. MVC session过期如何处理跳转

    以前我们总是会写一个基类也叫父类来判断session是否已过期然后跳转到指定的错误页面或者登陆界面,然后让所有的页面都继承这个基类,但是当我们应用到MVC项目中时,发现该方法并不会起作用.这时我们可以 ...

  6. python拷贝文件到多个文件夹

    主要用来做数据备份,每次用完以后再跑一次脚本,又可以将文件夹下的所有文件拷贝到指定的文件夹内 import os,sys,shutil; class cur_env: path = sys.path[ ...

  7. 轻松找回Win7桌面“消失”的IE9图标

    打开注册表编辑器(Win+R打开运行窗口,运行regedit命令),依次展开到 [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion ...

  8. Handler 取不到session 解决办法

      Handler需要继承 Handler : IHttpHandler, IReadOnlySessionState, IRequiresSessionState

  9. poj1840 哈希

    虽然这题目我曾经在我们学校OJ上做过但是我那时候是用的暴力做的,这次我用的是哈希写的,我写这题目时候开始是在main函数里面写哈希感觉很麻烦很不清晰,然后我换用函数来写,清晰了很多,写完就AC了.用哈 ...

  10. Android IOS WebRTC 音视频开发总结(五十)-- 技术服务如何定价?

    这篇文章最早是杜老师写的,看完感触很深,加上之前跟咨询公司的朋友也讨论过这方面的问题,所以结合自己的经验,做了些删改(得到了杜老师的授权). 先通过下面几个简单的问题来了解技术服务: 问题1:技术服务 ...