Android之一种很有趣的界面跳动提示动画
上一个效果图:
====================================
先上布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" > <RelativeLayout
android:id="@+id/red"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff0000" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/switch2blue"
android:layout_centerHorizontal="true"
android:text="首页" /> <Button
android:id="@+id/switch2blue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="置换位蓝色" />
</RelativeLayout> <RelativeLayout
android:id="@+id/blue"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000ff" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/switch2red"
android:layout_centerHorizontal="true"
android:text="第二页" /> <Button
android:id="@+id/switch2red"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="置换位红色" />
</RelativeLayout> </RelativeLayout>
代码:
import java.lang.reflect.Field;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.Button;
import android.widget.RelativeLayout; public class MainActivity extends Activity implements OnClickListener,
OnTouchListener, OnGestureListener { private RelativeLayout red, blue;
private Button switch2blue, switch2red; private float thisDelta = 0.05f;
private static boolean hasEverPulled = false;
private boolean pulled = false;
private static int height;
private GestureDetector gestureDetector;
private static int statusHeight = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); DisplayMetrics metrics = getResources().getDisplayMetrics();
height = metrics.heightPixels; statusHeight = getStatusHeight(); initView(); // 跳动提示可以上拉
final Handler handler = new Handler();
handler.postDelayed(new Runnable() { @Override
public void run() {
jump(thisDelta);
// handler.postDelayed(this, 3000);
}
}, 3000); } private void initView() {
red = (RelativeLayout) findViewById(R.id.red);
blue = (RelativeLayout) findViewById(R.id.blue); switch2blue = (Button) findViewById(R.id.switch2blue);
switch2red = (Button) findViewById(R.id.switch2red); switch2blue.setOnClickListener(this);
switch2red.setOnClickListener(this);
blue.setOnTouchListener(this);
blue.setLongClickable(true);
gestureDetector = new GestureDetector(this, this);
} @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
switch (arg0.getId()) {
case R.id.switch2blue: red2BlueUI();
break; case R.id.switch2red:
blue2RedUI();
break;
}
} // 从红页面转到蓝页面
private void red2BlueUI() {
blue.bringToFront();
blue.requestLayout();
blue.invalidate();
} // 从蓝页面转到红页面
private void blue2RedUI() {
red.bringToFront();
red.requestLayout();
red.invalidate();
} // 获取状态栏的高度
private int getStatusHeight() {
Class<?> c = null;
Object obj = null;
Field field = null;
int x = 0;
int height = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
height = getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
} return height;
} // 主页面跳动
private void jump(float delta) {
if (thisDelta - 0.03f < 0.001f) {
thisDelta = 0.05f;
return;
}
thisDelta = delta; if (hasEverPulled) {
return;
}
playJumpAnimation(thisDelta);
} // 上拉/下拉主页面
private void pull(boolean upward) {
if (upward && pulled) {
return;
}
if (!upward && !pulled) {
return;
} float originalY;
float finalY;
if (!pulled) {
originalY = 0;
finalY = (float) (0 - height + 0.4 * height);
} else {
originalY = (float) (0 - height + 0.4 * height);
finalY = 0;
}
pulled = !pulled; AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(new TranslateAnimation(0, 0, originalY,
finalY)); animationSet.setDuration(300);
animationSet.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet.setFillAfter(true); animationSet.setAnimationListener(new AnimationListener() { @Override
public void onAnimationStart(Animation animation) {
if (!pulled) {
red2BlueUI();
}
} @Override
public void onAnimationRepeat(Animation animation) { } @Override
public void onAnimationEnd(Animation animation) {
// if (pulled) {
// blue2RedUI();
// }
}
}); blue.startAnimation(animationSet); hasEverPulled = true;
} // 跳起动画
private void playJumpAnimation(final float delta) {
float originalY = 0;
float finalY = 0 - height * delta;
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(new TranslateAnimation(0, 0, originalY,
finalY)); animationSet.setDuration(300);
animationSet.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet.setFillAfter(true); animationSet.setAnimationListener(new AnimationListener() { @Override
public void onAnimationStart(Animation animation) {
} @Override
public void onAnimationRepeat(Animation animation) {
} @Override
public void onAnimationEnd(Animation animation) {
playLandAnimation(delta);
}
}); blue.startAnimation(animationSet);
} // 落下动画
private void playLandAnimation(final float delta) {
float originalY = 0 - height * delta;
float finalY = 0;
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(new TranslateAnimation(0, 0, originalY,
finalY)); animationSet.setDuration(200);
animationSet.setInterpolator(new AccelerateInterpolator());
animationSet.setFillAfter(true); animationSet.setAnimationListener(new AnimationListener() { @Override
public void onAnimationStart(Animation animation) {
} @Override
public void onAnimationRepeat(Animation animation) {
} @Override
public void onAnimationEnd(Animation animation) {
jump(0.03f);
}
}); blue.startAnimation(animationSet);
} @Override
public boolean onDown(MotionEvent e) {
pull(false); return false;
} @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// 手势滑动达到100才触发
if (e1.getY() - e2.getY() > 100) {
pull(true);
} else if (e2.getY() >= e1.getY()) {
pull(false);
} return false;
} @Override
public void onLongPress(MotionEvent e) {
} @Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
} @Override
public void onShowPress(MotionEvent e) {
} @Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
} @Override
public boolean onTouch(View v, MotionEvent event) {
if (pulled) {
// 首张页可触控点
if (event.getY() > height * 0.4 - statusHeight) {
return false;
}
} return gestureDetector.onTouchEvent(event);
}
}
Android之一种很有趣的界面跳动提示动画的更多相关文章
- Android学习系列(23)--App主界面实现
在上篇文章<Android学习系列(22)--App主界面比较>中我们浅略的分析了几个主界面布局,选了一个最大众化的经典布局.今天我们就这个经典布局,用代码具体的实现它. 1.预览图先看下 ...
- Android系统编程入门系列之界面Activity绘制展示
上篇文章介绍了界面Activity的启动方式和生命周期,本篇将继续介绍在界面Activity中的内容是如何绘制展示给用户的. 在Android系统上运行新创建的界面Activtiy,给用户展示的是空白 ...
- Android 三种动画详解
[工匠若水 http://blog.csdn.net/yanbober 转载请注明出处.点我开始Android技术交流] 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让 ...
- Android五种数据存储方式
android 五种数据存储 :SharePreferences.SQLite.Contert Provider.File.网络存储 Android系统提供了四种存储数据方式.分别为:SharePre ...
- (转) 机器学习很有趣Part6:怎样使用深度学习进行语音识别
本文转自:http://www.jiqizhixin.com/article/2321 机器学习很有趣Part6:怎样使用深度学习进行语音识别 2017-02-19 13:20:47 机器学习 ...
- iOS中三种方式实现登录界面播放视频或gif效果
现在app都做的越来越炫酷,各种动画效果,各种特效很好的提高了用户的体验.很多app在登录界面都使用了动画效果,比如Uber,Keep,QQ等等.这些动画效果基本都是使用gif或者MP4来实现的. 效 ...
- Android studio 开发一个用户登录界面
Android studio 开发一个用户登录界面 activity_main.xml <?xml version="1.0" encoding="utf-8&qu ...
- Android 四种加载方式详解(standard singleTop singleTask singleInstance) .
Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...
- Android系统编程入门系列之界面Activity响应丝滑的传统动画
上篇文章介绍了应用程序内对用户操作响应的相关方法位置,简单的响应逻辑可以是从一个界面Activity跳转到另一个界面Activity,也可以是某些视图View的相对变化.然而不管是启动一个界面执行新界 ...
随机推荐
- .NetCore源码阅读笔记系列之Security (一) Authentication & AddCookie
如果你使用过.NetCore开发过程序,你会很清楚,在其中我们经常会用到一些如下的代码 services.AddAuthentication(options => { options.Defau ...
- js 相对路径转为绝对路径
有时为了唯一标识网址或其它开发需要,我们需要将相对的网址转换为绝对的网址.当然前人实现方式已经不少,但或多或少的存在缺点或兼容问题.下面我将总结已有实现并给出相对完美的实现. 常规实现:地址转换 因该 ...
- docker重命名镜像
一.docker tag IMAGEID(镜像id) REPOSITORY:TAG(仓库:标签)
- Flume分布式日志收集系统
1.flume是分布式的日志收集系统,把收集来的数据传送到目的地去.2.flume里面有个核心概念,叫做agent.agent是一个java进程,运行在日志收集节点.通过agent接收日志,然后暂存起 ...
- 关于spark ui中executor显示的内存量与设置的内存量不符的问题
executor显示的内存量是实际执行程序使用的内存量,也就是排除bspark.storage.memoryFraction设置的比例外,然后使用的内存量. 默认是0.6,所以executory和dr ...
- WinSCP命令行操作
WinSCP命令行操作 WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端.同时支持SCP协议.它的主要功能就是在本地与远程计算机间安全的复制文件. 直接在cmd下输入 ...
- Python3 kmeans 聚类算法
# -*- coding: utf-8 -*- """ Created on Wed Jan 10 19:18:56 2018 @author: markli " ...
- Vue.js学以致用之遇到的那些坑
前段时间的react授权许可的闹剧告诉大家一个问题,只有自己的东西用着才放心.各大巨头也逐渐明白使用自家东西的优势.本来vue的生态就愈加火热,这次的闹剧无疑又加速了vue的发展.当下,国内越来越多的 ...
- [转]C++实现平衡二叉树
作者:Rest探路者 出处:http://www.cnblogs.com/Java-Starter/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意请保留此段声明,请在文章页面明显位置给出原文 ...
- Java集合&Spring源码浅读
记录自己现在知道的,以后了解了更多的话,再继续补上来 Java集合类 Collection 接口 说明:是List,set 的父类.定义了集合初始模样.集合只存储对象. Jdk8文档,内部方法定义有: ...