可上下拖动且有浮沉动画的View
package com.ifenglian.superapp1; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout; /**
* 可上下拖动且有浮沉动画的View
* create by shixm on 2017/5/17 15:11
*/
public class SHDrawerAnimLayerLayout extends FrameLayout { private static final String OBJECT_ANIMATION_PROPERTY_NAME = "translationY"; // 可拖动的顶部View
private View viewTopDragView;
// 可拖动的底部View
private View viewBottomDragView; // View在关状态,露出的高度
private int viewVisibleHeight = 50;
// 可识别触摸事件的高度
private int touchHeight = 50;
// 顶部View偏移Y
private int topViewTranslationY;
// 底部View偏移Y
private int bottomViewTranslationY;
// 顶部View是否在触摸范围
private boolean isTopViewInRect;
// 底部View是否在触摸范围
private boolean isBottomViewInRect; public SHDrawerAnimLayerLayout(Context context, View topView, View bottomView) {
this(context);
setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
addView(topView);
addView(bottomView);
viewTopDragView = topView;
viewBottomDragView = bottomView;
viewTopDragView.setAlpha(1);
viewBottomDragView.setAlpha(0);
} public SHDrawerAnimLayerLayout(Context context) {
super(context, null);
} @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
topViewTranslationY = - viewVisibleHeight;
viewTopDragView.setY(topViewTranslationY);
bottomViewTranslationY = viewVisibleHeight;
viewBottomDragView.setY(bottomViewTranslationY);
} @Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
float downX = event.getX();
float downY = event.getY();
if (!isInTopViewRect(downX, downY)) {
isTopViewInRect = false;
} else {
isTopViewInRect = true;
}
if (!isInBottomViewRect(downX, downY)) {
isBottomViewInRect = false;
} else {
isBottomViewInRect = true;
}
break;
case MotionEvent.ACTION_MOVE:
if (isTopViewInRect) {
float moveY = event.getY();
if (moveY >= 0 && moveY < getHeight()) {
viewTopDragView.setY(-getHeight() + moveY);
float alpha = moveY / getHeight();
viewTopDragView.setAlpha(alpha);
viewBottomDragView.setAlpha(1 - alpha);
}
}
if (isBottomViewInRect) {
float moveY = event.getY();
if (moveY >= 0 && moveY < getHeight()) {
viewBottomDragView.setY(moveY);
float alpha = moveY / getHeight();
viewTopDragView.setAlpha(alpha);
viewBottomDragView.setAlpha(1 - alpha);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (isTopViewInRect) {
if (viewTopDragView.getTranslationY() < -getHeight() / 2) {
topViewScrollToTop();
} else {
topViewScrollToBottom();
}
isTopViewInRect = false;
}
if (isBottomViewInRect) {
if (viewBottomDragView.getTranslationY() < getHeight() / 2) {
bottomViewScrollToTop();
} else {
bottomViewScrollToBottom();
}
isBottomViewInRect = false;
}
break;
}
return true;
} private void bottomViewScrollToTop() {
ObjectAnimator topAnimation = ObjectAnimator.ofFloat(viewBottomDragView, OBJECT_ANIMATION_PROPERTY_NAME, viewBottomDragView.getTranslationY(), viewVisibleHeight);
topAnimation.start();
} private void topViewScrollToTop() {
ObjectAnimator topAnimation = ObjectAnimator.ofFloat(viewTopDragView, OBJECT_ANIMATION_PROPERTY_NAME, viewTopDragView.getTranslationY(), -getHeight() + viewVisibleHeight);
topAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ObjectAnimator.ofFloat(viewTopDragView, OBJECT_ANIMATION_PROPERTY_NAME, viewTopDragView.getTranslationY(), -viewVisibleHeight).setDuration(0).start();
viewTopDragView.setAlpha(0);
}
});
topAnimation.start();
} private void bottomViewScrollToBottom() {
ObjectAnimator bottomAnimation = ObjectAnimator.ofFloat(viewBottomDragView, OBJECT_ANIMATION_PROPERTY_NAME, viewBottomDragView.getTranslationY(), getHeight() - bottomViewTranslationY);
bottomAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
viewBottomDragView.setAlpha(0);
ObjectAnimator.ofFloat(viewBottomDragView, OBJECT_ANIMATION_PROPERTY_NAME, viewBottomDragView.getTranslationY(), bottomViewTranslationY).setDuration(0).start();
viewTopDragView.setAlpha(1);
}
});
bottomAnimation.start();
} private void topViewScrollToBottom() {
ObjectAnimator bottomAnimation = ObjectAnimator.ofFloat(viewTopDragView, OBJECT_ANIMATION_PROPERTY_NAME, viewTopDragView.getTranslationY(), (topViewTranslationY));
bottomAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
viewBottomDragView.setAlpha(0);
viewTopDragView.setAlpha(1);
}
});
bottomAnimation.start();
} private boolean isInTopViewRect(float downX, float downY) {
if (downX > viewTopDragView.getLeft() && downX < viewTopDragView.getRight()) {
if (downY >= viewTopDragView.getTranslationY() + getHeight() - touchHeight && downY <= viewTopDragView.getTranslationY() + getHeight()) {
return true;
}
}
return false;
} private boolean isInBottomViewRect(float downX, float downY) {
if (downX > viewBottomDragView.getLeft() && downX < viewBottomDragView.getRight()) {
if (downY >= viewBottomDragView.getTranslationY() && downY <= touchHeight + viewBottomDragView.getTranslationY()) {
return true;
}
}
return false;
}
} 使用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); LinearLayout lin = new LinearLayout(this);
lin.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); RelativeLayout relativeLayout1 = new RelativeLayout(this);
RelativeLayout.LayoutParams reParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dip2px(this, 310));
relativeLayout1.setLayoutParams(reParams);
relativeLayout1.setBackgroundColor(Color.parseColor("#00FF00")); RelativeLayout relativeLayout2 = new RelativeLayout(this);
RelativeLayout.LayoutParams reParams2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dip2px(this, 310));
relativeLayout2.setLayoutParams(reParams2);
relativeLayout2.setBackgroundColor(Color.parseColor("#0000FF")); SHDrawerAnimLayerLayout dragLayout = new SHDrawerAnimLayerLayout(this, relativeLayout1, relativeLayout2);
dragLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
dragLayout.setBackgroundColor(Color.parseColor("#000000"));
lin.addView(dragLayout); lin.setBackgroundColor(Color.WHITE);
setContentView(lin);
}
可上下拖动且有浮沉动画的View的更多相关文章
- Android 动画基础——视图动画(View Animation)
本篇讲android 3.0之前被广泛的动画框架——ViewAnimation. 目录 我将分为六部分来讲: 概述 Alpha透明动画 Rotate旋转动画 Translate位移动画 Scale放缩 ...
- *C#(WPF)--矩阵拖动和矩阵动画(拖动展开,不足动画效果)
最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画.之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来: 我的开发环境是在VS2017下进行 ...
- 动画效果 View控件的显示和隐藏效果
显示动画: mShowAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_ ...
- 【转】2D动画:view的Matrix
Matrix,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放.平移.旋转等操作. 首先介绍一下矩阵运算.加法和减法就不用说了,太简单了,对应位相加就好.图像处理,主要用到的是乘法 ...
- 在Android中动画移动一个View的位置,采用Scroller类实现Android动画之 View移动
在Android中动画移动一个View的位置,采用Scroller类实现 今天说最近自己遇到的一个问题,就是要用动画效果来移动一个VIew的位置. 这个具体的情况是,需要做一个SlidingMenu的 ...
- Android 用属性动画自定义view的渐变背景
自定义view渐变背景,同时监听手势自动生成小圆球. 宿主Activity如下: package com.edaixi.tempbak; import java.util.ArrayList; imp ...
- Android 动画之View动画效果和Activity切换动画效果
View动画效果: 1.>>Tween动画通过对View的内容进行一系列的图形变换(平移.缩放.旋转.透明度变换)实现动画效果,补间动画需要使用<set>节点作为根节点,子节点 ...
- ios假设写一个提示带动画的View,能够来引导用户行为
先上图: 这个UIView能够这样写: -(id)initWithFrame:(CGRect)frame backImage:(UIImage*)image msgStr:(NSString*)txt ...
- 每日一问:到底为什么属性动画后 View 在新位置还能响应事件
在 Android 开发中,我们难免会使用动画来处理各种各样的动画效果,以满足 UI 的高逼格设计.对于比较复杂的动画效果,我们通常会采用著名的开源库:lottie-android,或许你会对 lot ...
随机推荐
- 29.Mongodb可视化工具 Studio 3t
Studio 3T 链接地址:https://pan.baidu.com/s/1X-Sqk50Xm76NJIZOz0ehFw 密码:td2a 安装配置成功链接本地如图所示:
- 42. oracle通过两张表的一个字段对应,update其中一张表的某个字段
update A a set a.A2 = (select b.B2 from B b where b.B1=a.A1) where exists (select 1 from B where B.B ...
- 1. easyui tree 初始化的两种方式
/** * 查询角色分类 */function queryRoleCategoryTree(selectId) { var url = basePath + 'rest/roleCategoryCon ...
- Valgrind简单用法 (转)
转自 http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html Valgrind的主要作者Julian Seward刚获得了今年的G ...
- SonarQube与Jenkins结合提高代码质量
首先,为什么需要SonarQube? 1.WriteClean Code 1)全局健康报告 2)关注新增的问题 3)强制QualityGate 4)Issue详情及建议- 详情参考:https:/ ...
- mysql innodb count(*)速度慢且不准确的解决办法
innodb引擎在统计方面和myisam是不同的,Myisam内置了一个计数器,所以在使用 select count(*) from table 的时候,直接可以从计数器中取出数据.而innodb必须 ...
- postman 的基础使用
https://blog.csdn.net/fxbin123/article/details/80428216
- Delphi FrieDAC 大数据处理
Delphi FrieDAC 大数据处理 大数据处理, 要用到Array DML 插入数据 先要设置插入的数据量 FQuery1.Params.ArraySize := 1000; for index ...
- jeecg使用小结
1.上传word模板时报“java.lang.UnsatisfiedLinkError: no jacob-1.17-M2-x64 in java.library.path”异常 原因:jdk下没有找 ...
- ASP.NET Form身份验证方式详解
注:不会涉及ASP.NET的登录系列控件以及membership的相关话题, 我只想用比较原始的方式来说明在ASP.NET中是如何实现身份认证的过程. ASP.NET身份认证基础 在开始今天的博客 ...