首页 > 代码库 > Android自定义控件(四)——让每一个Activity UI都具有弹性

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

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

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

先上图:

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

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

改动如下:

 

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


本次教程就到此,

 

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

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