Android自定义控件(四)——让每一个Activity UI都具有弹性

前面我们已经介绍了如何让你的ScrollView,ListView具有弹性,

今天,我们在前面的基础上,做一下适当的修改,让那些既不是ScrollView,也不是ListView的Activity页面,也能具有弹性。

先上图:

图中是最简单的一个Android测试程序。默认的效果TextView是无法划动的。

进过我们小小的改造,就能让整个UI具有弹性效果。

改动如下:

[java] view plaincopy

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. View view = getLayoutInflater().inflate(R.layout.activity_main, null);
  4. view.setOnTouchListener(new ElasticTouchListener());
  5. setContentView(view);
  6. }

我们仅仅只需要在需要弹性的Root VIew 上加上监听。就能达到如果的效果了。

ElasticTouchListener源码:

[java] view plaincopy

  1. public class ElasticTouchListener implements OnTouchListener {
  2. private View inner;
  3. View[] children;
  4. private float y;
  5. private Rect normal = new Rect();
  6. private boolean animationFinish = true;
  7. private int[] tops;
  8. private int[] bottoms;
  9. @Override
  10. public boolean onTouch(View v, MotionEvent ev) {
  11. if (inner == null && children == null) {
  12. if (v instanceof ViewGroup) {
  13. ViewGroup group = (ViewGroup) v;
  14. int count = group.getChildCount();
  15. if (count > 0) {
  16. children = new View[count];
  17. tops = new int[count];
  18. bottoms = new int[count];
  19. for (int i = 0; i < count; i++) {
  20. children[i] = group.getChildAt(i);
  21. tops[i] = children[i].getTop();
  22. bottoms[i] = children[i].getBottom();
  23. }
  24. }
  25. }
  26. inner = v;
  27. }
  28. if (animationFinish && (inner != null || children != null)) {
  29. int action = ev.getAction();
  30. switch (action) {
  31. case MotionEvent.ACTION_DOWN:
  32. //              System.out.println("ACTION_DOWN");
  33. y = ev.getY();
  34. break;
  35. case MotionEvent.ACTION_UP:
  36. //              System.out.println("ACTION_UP");
  37. y = 0;
  38. if (isNeedAnimation()) {
  39. animation();
  40. }
  41. inner.invalidate();
  42. break;
  43. case MotionEvent.ACTION_MOVE:
  44. //              System.out.println("ACTION_MOVE");
  45. final float preY = y == 0 ? ev.getY() : y;
  46. float nowY = ev.getY();
  47. int deltaY = (int) (preY - nowY);
  48. y = nowY;
  49. // 当滚动到最上或者最下时就不会再滚动,这时移动布局
  50. if (isNeedMove()) {
  51. if (normal.isEmpty()) {
  52. // 保存正常的布局位置
  53. normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());
  54. }
  55. if (children != null) {
  56. View view = null;
  57. for (int i = 0; i < children.length; i++) {
  58. view = children[i];
  59. view.layout(view.getLeft(), view.getTop() - deltaY / 2, view.getRight(), view.getBottom() - deltaY / 2);
  60. }
  61. } else {
  62. // 移动布局
  63. inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom() - deltaY / 2);
  64. }
  65. }
  66. inner.invalidate();
  67. break;
  68. default:
  69. break;
  70. }
  71. } else {
  72. return false;
  73. }
  74. return true;
  75. }
  76. // 开启动画移动
  77. public void animation() {
  78. if (children == null) {
  79. // 开启移动动画
  80. TranslateAnimation trans = new TranslateAnimation(0, 0, 0, normal.top - inner.getTop());
  81. trans.setDuration(200);
  82. trans.setAnimationListener(new AnimationListener() {
  83. @Override
  84. public void onAnimationStart(Animation animation) {
  85. animationFinish = false;
  86. }
  87. @Override
  88. public void onAnimationRepeat(Animation animation) {
  89. }
  90. @Override
  91. public void onAnimationEnd(Animation animation) {
  92. inner.clearAnimation();
  93. // 设置回到正常的布局位置
  94. inner.layout(normal.left, normal.top, normal.right, normal.bottom);
  95. normal.setEmpty();
  96. animationFinish = true;
  97. }
  98. });
  99. inner.startAnimation(trans);
  100. } else {
  101. for (int i = 0; i < children.length; i++) {
  102. final View view = children[i];
  103. if (view.getVisibility() == View.VISIBLE) {
  104. final int index = i;
  105. // 开启移动动画
  106. TranslateAnimation trans = new TranslateAnimation(0, 0, 0, tops[i] - view.getTop());
  107. trans.setDuration(200);
  108. trans.setAnimationListener(new AnimationListener() {
  109. @Override
  110. public void onAnimationStart(Animation animation) {
  111. animationFinish = false;
  112. }
  113. @Override
  114. public void onAnimationRepeat(Animation animation) {
  115. }
  116. @Override
  117. public void onAnimationEnd(Animation animation) {
  118. view.clearAnimation();
  119. // 设置回到正常的布局位置
  120. view.layout(view.getLeft(), tops[index], view.getRight(), bottoms[index]);
  121. normal.setEmpty();
  122. animationFinish = true;
  123. }
  124. });
  125. view.startAnimation(trans);
  126. }
  127. }
  128. }
  129. }
  130. // 是否需要开启动画
  131. public boolean isNeedAnimation() {
  132. return !normal.isEmpty();
  133. }
  134. // 是否需要移动布局
  135. public boolean isNeedMove() {
  136. //      int offset = inner.getMeasuredHeight() - getHeight();
  137. //      int scrollY = getScrollY();
  138. //      if (scrollY == 0 || scrollY == offset) {
  139. //          return true;
  140. //      }
  141. //      return false;
  142. //      if (children != null && children.length > 0
  143. //              && (children[children.length - 1].getBottom() <= inner.getPaddingTop()/*inner.getTop()*/
  144. //              || children[0].getTop() >= inner.getHeight()
  145. //              )) {
  146. //          return false;
  147. //      }
  148. return true;
  149. }
  150. }

本次教程就到此,

经过有弹性的ScrollView有弹性的ListView,以及本文的介绍,就可以让你的Android应用在每一个角落都拥有弹性啦。

时间: 2024-10-05 05:02:33

Android自定义控件(四)——让每一个Activity UI都具有弹性的相关文章

Android开发:向下一个activity传递数据,返回数据给上一个activity

1.向下一个activity传递数据 activity1 1 Button button=(Button) findViewById(R.id.button1); 2 button.setOnClickListener(new OnClickListener() { 3 4 @Override 5 public void onClick(View v) { 6 Intent intent=new Intent("1111111111111111111"); 7 intent.addCa

android显示意图激活另一个Activity

android跳转到另一个界面,是app常用的操作.我们可以跳转到该应用本身的界面,亦可以跳转到系统的应用界面. 效果: 打开软件: 跳转到第二个界面: 跳转到系统应用的界面: 附代码如下: 主界面代码: 1 package com.yy.twoactivity; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.os.Bundle; 6 import android.view.V

Eclipse中在android项目中出现新建一个Activity后,出现整个工程的报错以及包导入以后无法运行等等情况分析。

今天用Eclipse去写android项目,然后后面需要建一个Blank  Activity后,很正常的建立的,然后那个Activity是基于ActionBarAtivity,要导入v7,结果因为这个v7的原因,导致原来的导入包不见了,而且重新导入的时候,虽然工程开启没有报错误,但是接下来在运行的时候,结果运行不了,Logcat出现Classnotfound,但是之前的工程一点事都有.折磨了半天,终于发现错误所在,兼容性问题就不说了,说一下应该怎么解决这样的报错.那就是在新建的时候,你新建一个E

Eclipse中在android项目中出现新建一个Activity后,出现整个project的报错以及包导入以后无法执行等等情况分析。

今天用Eclipse去写android项目,然后后面须要建一个Blank  Activity后,非常正常的建立的.然后那个Activity是基于ActionBarAtivity,要导入v7,结果由于这个v7的原因,导致原来的导入包不见了.并且又一次导入的时候,尽管project开启没有报错误,可是接下来在执行的时候,结果执行不了.Logcat出现Classnotfound,可是之前的project一点事都有.折磨了半天,最终发现错误所在,兼容性问题就不说了,说一下应该怎么解决这种报错.那就是在新

Android自定义控件(四)仿网易客户端上拉加载更多

上一篇仿得网页客户端的抽屉模式,这一篇继续,来写一写加载更多这个功能,通过自定义实现加载更多,先上图: 今天实现的就是如图中最下面的20条载入中...这个功能啦! 先来说一下思路: 1.在listview中加入20条载入中的这个布局并隐藏 2.加入OnScrollListener监听,通过监听滚动事件,当滚动到最低端的时候,显示上面的布局 3.通过接口回调实现加载更多的功能 4.加载完数据时,通知listview加载结束,隐藏上面的布局文件 下面直接上代码: 1.在listview中加入20条载

android自定义控件(四) View中的方法

onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) 确定所有子元素的大小 onLayout(boolean, int, int, int, int) 当View分配所有的子元素的大小和位置时触发 onSizeChanged(int, int, int, int) 当view的大小发生变化时触发 onDraw(Canvas) view渲染内容的细节 onKeyDown(int, KeyEvent) 有按键按下后触发 onKe

android 利用Handler触发另一个activity方法

如activityA代码: activityB = new ActivtyB(mHandler,CLOSE_SEARCH_MSG);//新建对像B传递,一个handler和Message,然后在activityB中发送即可触发activityA的方法: activityB代码: if (mHandler != null) { Message msg = new Message(); msg.what = CLOSE_SEARCH_MSG; mHandler.sendMessage(msg); }

【Android】学习日记一 初识Activity

一.Activity简介: Activity是Android组件中的最基本也是最常用的一种组件,在一个Android应用中,每一个Activity通常都是一个页面,每一个Activity都被实现为一个独立的类,可以理解为J2EE中的JSP页面.并且每个Activity组件都 继承于Activity这个基类,这个Activity类将会显示由几个Views控件组成的用户接口,并对事件作出响应 通过调用startActivity()方法可以从一个屏幕导航到另一个屏幕,打开Activity的条件被封装在

Android基础整理之四大组件Activity

最近准备系统的重新整理复习一下Android的各方面的知识,本着知识分享的原则,我就把梳理过程中一些东西给记录下来,权当一个学习笔记吧. 下面步入正题..... 什么是Activity Activity作为Android四大组件之一,也是其中最重要的一个组件.作为一个与用户交互的组件,我们可以把Activity比较成为windows系统上的一个文件夹窗口,是一个与用户交互的界面.再进一步说,当我们拿起Android打开拨号功能,显示出拨号盘的界面其实就是一个Activity:当然,可以更大范围的