Android自定义控件(四)——让每一个Activity UI都具有弹性
前面我们已经介绍了如何让你的ScrollView,ListView具有弹性,
今天,我们在前面的基础上,做一下适当的修改,让那些既不是ScrollView,也不是ListView的Activity页面,也能具有弹性。
先上图:
图中是最简单的一个Android测试程序。默认的效果TextView是无法划动的。
进过我们小小的改造,就能让整个UI具有弹性效果。
改动如下:
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- View view = getLayoutInflater().inflate(R.layout.activity_main, null);
- view.setOnTouchListener(new ElasticTouchListener());
- setContentView(view);
- }
我们仅仅只需要在需要弹性的Root VIew 上加上监听。就能达到如果的效果了。
ElasticTouchListener源码:
- public class ElasticTouchListener implements OnTouchListener {
- private View inner;
- View[] children;
- private float y;
- private Rect normal = new Rect();
- private boolean animationFinish = true;
- private int[] tops;
- private int[] bottoms;
- @Override
- public boolean onTouch(View v, MotionEvent ev) {
- if (inner == null && children == null) {
- if (v instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) v;
- int count = group.getChildCount();
- if (count > 0) {
- children = new View[count];
- tops = new int[count];
- bottoms = new int[count];
- for (int i = 0; i < count; i++) {
- children[i] = group.getChildAt(i);
- tops[i] = children[i].getTop();
- bottoms[i] = children[i].getBottom();
- }
- }
- }
- inner = v;
- }
- if (animationFinish && (inner != null || children != null)) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // System.out.println("ACTION_DOWN");
- y = ev.getY();
- break;
- case MotionEvent.ACTION_UP:
- // System.out.println("ACTION_UP");
- y = 0;
- if (isNeedAnimation()) {
- animation();
- }
- inner.invalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- // System.out.println("ACTION_MOVE");
- final float preY = y == 0 ? ev.getY() : y;
- float nowY = ev.getY();
- int deltaY = (int) (preY - nowY);
- y = nowY;
- // 当滚动到最上或者最下时就不会再滚动,这时移动布局
- if (isNeedMove()) {
- if (normal.isEmpty()) {
- // 保存正常的布局位置
- normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());
- }
- if (children != null) {
- View view = null;
- for (int i = 0; i < children.length; i++) {
- view = children[i];
- view.layout(view.getLeft(), view.getTop() - deltaY / 2, view.getRight(), view.getBottom() - deltaY / 2);
- }
- } else {
- // 移动布局
- inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom() - deltaY / 2);
- }
- }
- inner.invalidate();
- break;
- default:
- break;
- }
- } else {
- return false;
- }
- return true;
- }
- // 开启动画移动
- public void animation() {
- if (children == null) {
- // 开启移动动画
- TranslateAnimation trans = new TranslateAnimation(0, 0, 0, normal.top - inner.getTop());
- trans.setDuration(200);
- trans.setAnimationListener(new AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- animationFinish = false;
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- inner.clearAnimation();
- // 设置回到正常的布局位置
- inner.layout(normal.left, normal.top, normal.right, normal.bottom);
- normal.setEmpty();
- animationFinish = true;
- }
- });
- inner.startAnimation(trans);
- } else {
- for (int i = 0; i < children.length; i++) {
- final View view = children[i];
- if (view.getVisibility() == View.VISIBLE) {
- final int index = i;
- // 开启移动动画
- TranslateAnimation trans = new TranslateAnimation(0, 0, 0, tops[i] - view.getTop());
- trans.setDuration(200);
- trans.setAnimationListener(new AnimationListener() {
- @Override
- public void onAnimationStart(Animation animation) {
- animationFinish = false;
- }
- @Override
- public void onAnimationRepeat(Animation animation) {
- }
- @Override
- public void onAnimationEnd(Animation animation) {
- view.clearAnimation();
- // 设置回到正常的布局位置
- view.layout(view.getLeft(), tops[index], view.getRight(), bottoms[index]);
- normal.setEmpty();
- animationFinish = true;
- }
- });
- view.startAnimation(trans);
- }
- }
- }
- }
- // 是否需要开启动画
- public boolean isNeedAnimation() {
- return !normal.isEmpty();
- }
- // 是否需要移动布局
- public boolean isNeedMove() {
- // int offset = inner.getMeasuredHeight() - getHeight();
- // int scrollY = getScrollY();
- // if (scrollY == 0 || scrollY == offset) {
- // return true;
- // }
- // return false;
- // if (children != null && children.length > 0
- // && (children[children.length - 1].getBottom() <= inner.getPaddingTop()/*inner.getTop()*/
- // || children[0].getTop() >= inner.getHeight()
- // )) {
- // return false;
- // }
- return true;
- }
- }
本次教程就到此,
经过有弹性的ScrollView,有弹性的ListView,以及本文的介绍,就可以让你的Android应用在每一个角落都拥有弹性啦。
转载于:https://www.cnblogs.com/Free-Thinker/p/4126091.html
Android自定义控件(四)——让每一个Activity UI都具有弹性相关推荐
- Android自定义控件(四)——望远镜效果实现
通常在两种情况下人们会思变求新:一种是希望摆脱危机,另一种只是单纯地想要一些新鲜的改变,没有什么特别迫切的需要.在前者,发出期盼的人即不幸福也不富足,而后者幸福而富裕.(不明之事乃命运之域,确定之事乃 ...
- android 多个fragment切换,一个Activity中多个Fragment的切换
经常会遇到在一个activity界面上布局多个fragment,但是如何从一个fragment跳转到另一个fragment呢?今天在做项目中恰好遇到这样的问题,点击首页fragment的更多店铺,会切 ...
- android碎片调用动态碎片,Android Training - 使用碎片创建一个动态UI
为了能够在Android中创建动态和多窗口的用户界面,你需要封装UI组件和activity行为在不同的模块中,以便你可以在不同的activity间切换.你可以使用Fragment类创建这些模块,类似于 ...
- Android自定义控件(四)仿网易客户端上拉加载更多
上一篇仿得网页客户端的抽屉模式,这一篇继续,来写一写加载更多这个功能,通过自定义实现加载更多,先上图: 今天实现的就是如图中最下面的20条载入中...这个功能啦! 先来说一下思路: 1.在listvi ...
- Android开发四 开发第一个Android应用
打开Eclipse,新建项目(点击FileNewProject),在项目列表中展开Android目录,选择Android Project,如下图: 点击"finish"即可完成 ...
- Android之 如何在退出一个activity后,很好的取消AsyncTask继续运行
public class Task extends AsyncTask<Void, Void, Void>{@Override protected Void doInBackground( ...
- 【Android】12.3 在当前Activity中获取另一个Activity的返回值
分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 在上一节的示例中,通过StartActivity(Intent)方法启动另一个Activity后,这两个Activ ...
- Android Studio App开发入门之在活动之间传递消息(附源码 超详细必看)(包括显示和隐式Intent,向上一个和下一个Activity发送数据)
运行有问题或需要源码请点赞关注收藏后评论区留言~~ 显示Intent和隐式Intent Intent是各个组件之间的信息沟通的桥梁,既能在Activity之间沟通,又能在Activity与Servi ...
- android 一个activity定时更新另一个activity的UI
在开发软件的过程中,客户提出了一个要求,就是在Mainactivity的一个按键button按下之后进入另一个OtherActivity,在这个OtherActivity完成了功能之后,按键butto ...
- 【转】android之在activity中控制另一个activity的UI更新_如何在activity之间传递handler...
来自:http://blog.csdn.net/jason0539/article/details/18055259 遇到一个问题,需要在一个activity中控制另一个acitivity做一些更新, ...
最新文章
- vs2017python找不到包_关于Python在VS2017版中编译C源代码出现的各种问题解决方法...
- python输入一个\输出2个\问题
- 周学习进度----03
- 消息中间件kafka概述和安装
- 都是远程办公惹的祸!搜狗输入法为错误推送地震预警信息致歉
- composer安装扩展包异常
- android的xml登录,Android----xml文件中的控件的id设置
- OEL修改字符集失败 -bash: /root: is a directory
- 天勤数据结构代码——双链表
- 1元云购网站建设,一元云购网站制作,夺宝网站定制公司,一元云购源码开发
- r 语言 html,r语言出现加号
- TensorFlow 2.10 Unable to register cuBLAS factory Attempting to register factory for plugin cuBLAS方案
- 用js实现加载本地图片并显示并将图片信息上传至服务端
- 微信导航的门户网站(曾经的创业故事4)
- 新买的电脑,设置电脑
- 提供优质客户服务的5种方法
- 最新5G时代投资区块链源码全修复版+对接免签支付+搭建视频
- is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-
- 暴风酷播云二期配置_暴风播酷云二期 黑群晖
- wordpress创建_如何在WordPress中创建问卷(简易方式)
热门文章
- @Transactional(rollbackFor=Exception.class)的作用
- 解决IIS7.5及以后中URL文件名有加号或空格导致显示404错误的问题
- C++ 长字符串换行
- Excel文件导入mysql数据库
- lingo软件的基本使用方法_(PS软件)PHOTOSHOP基础操作和基本工具的使用
- Linux系统目录的作用你了解吗?
- linux开启mysql窗口_linux操作系统中如何查看是否开启了MySQL服务呢?
- kubernetes英语怎么读_小学三年级英语怎么学
- 面向对象(Python):学习笔记之类属性和类方法
- linux内核zfs,ZFS与Linux文件系统的变革