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的更多相关文章

  1. Android 动画基础——视图动画(View Animation)

    本篇讲android 3.0之前被广泛的动画框架——ViewAnimation. 目录 我将分为六部分来讲: 概述 Alpha透明动画 Rotate旋转动画 Translate位移动画 Scale放缩 ...

  2. *C#(WPF)--矩阵拖动和矩阵动画(拖动展开,不足动画效果)

    最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画.之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来: 我的开发环境是在VS2017下进行 ...

  3. 动画效果 View控件的显示和隐藏效果

    显示动画: mShowAction = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1.0f,     Animation.RELATIVE_ ...

  4. 【转】2D动画:view的Matrix

    Matrix,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放.平移.旋转等操作. 首先介绍一下矩阵运算.加法和减法就不用说了,太简单了,对应位相加就好.图像处理,主要用到的是乘法 ...

  5. 在Android中动画移动一个View的位置,采用Scroller类实现Android动画之 View移动

    在Android中动画移动一个View的位置,采用Scroller类实现 今天说最近自己遇到的一个问题,就是要用动画效果来移动一个VIew的位置. 这个具体的情况是,需要做一个SlidingMenu的 ...

  6. Android 用属性动画自定义view的渐变背景

    自定义view渐变背景,同时监听手势自动生成小圆球. 宿主Activity如下: package com.edaixi.tempbak; import java.util.ArrayList; imp ...

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

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

  8. ios假设写一个提示带动画的View,能够来引导用户行为

    先上图: 这个UIView能够这样写: -(id)initWithFrame:(CGRect)frame backImage:(UIImage*)image msgStr:(NSString*)txt ...

  9. 每日一问:到底为什么属性动画后 View 在新位置还能响应事件

    在 Android 开发中,我们难免会使用动画来处理各种各样的动画效果,以满足 UI 的高逼格设计.对于比较复杂的动画效果,我们通常会采用著名的开源库:lottie-android,或许你会对 lot ...

随机推荐

  1. workerman-todpole 执行流程(1)

    该系列文章主要是彻底扒一下 workerman todpole 游戏的实现原理. 提前打个预防针: 由于 Worker 类的静态属性和子类对象的混用(当前类的静态属性存放当前类对象,静态方法循环静态属 ...

  2. node-disconf-client基本配置

    node-disconf-client 需要cppm install node-disconf-client var  disconf  = require (' node-disconf-clien ...

  3. 如何消除“为帮助保护您的安全,Internet Explorer 已经限制此文件显示可能访问您计算机

    如何消除“为帮助保护您的安全,Internet Explorer 已经限制此文件显示可能访问您计算机的活动内容.单击此处查看选项...”每次打开都出现警告音,可以打开浏览器的工具--> Inte ...

  4. HTML5 Canvas 小例子 简易画板

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. 【JEECG技术文档】JEECG高级查询构造器使用说明

    功能介绍   高级查询构造器支持主子表联合查询,查询出更精确的数据. 要使用高级查询构造器需要完成以下步骤: 1. 在高级查询管理配置主子表信息. 2. 配置完后在JSP页面DataGrid标签上添加 ...

  6. day25-面向对象结构与成员

    1.面向对象结构分析 如下面的图所示:面向对象整体大致分两块区域: 每个大区域又可以分为多个小部分: class A: name = 'Tom' # 静态变量(静态字段) __iphone = '13 ...

  7. Mycat 水平拆分

    一致性Hash理解 https://blog.csdn.net/cywosp/article/details/23397179?utm_source=blogxgwz1 十种 水平拆分 https:/ ...

  8. wed开发基础--练习题

    一.HTML部分 本小节重点: 熟练使用div+span布局,知道div和span的语义化的意思 熟悉对div.ul.li.span.a.img.table.form.input标签有深刻的认知, 初 ...

  9. JSP基本

    JSPとは.HTMLファイルにJavaコードを埋め込んでおき.クライアントの要求に応じてコードを実行.処理結果のみをクライアントに送信する技術です. 1.JSPは実はサーブレットです.最初にリクエスト ...

  10. [ JAVA编程 ] double类型计算精度丢失问题及解决方法

    前言 如果你在测试金融相关产品,请务必覆盖交易金额为小数的场景.特别是使用Java语言的初级开发. Java基本实例 先来看Java中double类型数值加.减.乘.除计算式实例: public cl ...