更新说明:

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. 剑指Offer:面试题7——用两个栈实现队列(java实现)

    题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 首先定义两个栈 Stack<Integer> stack1 = new Stack<I ...

  2. Android中MenuInflater实例

    我们知道,LayoutInflater是用来实例化整个布局文件,而MenuInflater是用来实例化Menu目录下的Menu布局文件的. 传统意义上的菜单定义需要Override Activity的 ...

  3. 纯CSS最小响应网格布局

    lemonade.css是一个超级小的CSS可以帮助你创建一个完全响应和灵活自如的网格布局,包括所需网页的头部. 样式链接 <link rel= href=> HTML结构这样创建一个多列 ...

  4. 【LeetCode】19. Remove Nth Node From End of List

    题目: 思路:如果链表为空或者n小于1,直接返回即可,否则,让链表从头走到尾,每移动一步,让n减1. 1.链表1->2->3,n=4,不存在倒数第四个节点,返回整个链表 扫过的节点依次:1 ...

  5. 8051学习笔记——AD

    AD.C #include<reg52.h> #include <iic.h> #define PCF8591 0x90 //PCF8591 地址 sbit LS138A=P2 ...

  6. [oracle] listener.ora 、sqlnet.ora 、tnsnames.ora

    路径 $ORACLE_HOME/network/admin sqlnet.ora(客户及服务器端) 作用类似于linux或者其他unix的nsswitch.conf文件,通过这个文件来决定怎么样找一个 ...

  7. python中时间和时区

    1.时区 http://blog.csdn.net/cz157733055/article/details/38319195 2.时间 datetime.timedelta代表两个时间之间的的时间差 ...

  8. table extraction

    http://yz.mit.edu/papers/webtables-vldb08.pdf http://www.vldb.org/pvldb/vol4/p528-venetis.pdf Alon H ...

  9. No.008 String to Integer (atoi)

    8. String to Integer (atoi) Total Accepted: 112863 Total Submissions: 825433 Difficulty: Easy Implem ...

  10. jquery递归遍历xml文件,形成ul-li序列,生成树结构(使用了treeview插件)

    treeview插件从这里获得,下载的文件中有demo,看demo文件夹里面的index.html文件就差不多知道如何使用该控件了,在我做的项目里用到的部分代码截图如下(在引用下面的js文件前要先引用 ...