【转】Android自定义控件(三)——有弹性的ListView

原文地址:http://blog.csdn.net/a105865708/article/details/17959459

上一次我们试验了有弹性的ScrollView。详情

这一次,我们来试验有弹性的ScrollView。

国际惯例,效果图:



主要代码:

  

  1 import android.content.Context;
  2 import android.graphics.Rect;
  3 import android.util.AttributeSet;
  4 import android.view.MotionEvent;
  5 import android.view.animation.Animation;
  6 import android.view.animation.Animation.AnimationListener;
  7 import android.view.animation.TranslateAnimation;
  8 import android.widget.AbsListView;
  9 import android.widget.ListView;
 10 
 11 /**
 12  * ElasticScrollView有弹性的ListView
 13  */
 14 public class ElasticListView extends ListView {
 15     private float y;
 16     private Rect normal = new Rect();
 17     private boolean animationFinish = true;
 18 
 19     public ElasticListView(Context context) {
 20         super(context);
 21         init();
 22     }
 23 
 24     public ElasticListView(Context context, AttributeSet attrs) {
 25         super(context, attrs);
 26         init();
 27     }
 28 
 29     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
 30 
 31     }
 32 
 33     boolean overScrolled = false;
 34     private void init() {
 35         setOnScrollListener(new OnScrollListener() {
 36             @Override
 37             public void onScrollStateChanged(AbsListView view, int scrollState) {
 38             }
 39 
 40             @Override
 41             public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
 42                 overScrolled = false;
 43             }
 44         });
 45     }
 46     
 47     @Override
 48     protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
 49         overScrolled = true;
 50     }
 51 
 52     @Override
 53     public boolean onTouchEvent(MotionEvent ev) {
 54         commOnTouchEvent(ev);
 55         return super.onTouchEvent(ev);
 56     }
 57 
 58     public void commOnTouchEvent(MotionEvent ev) {
 59         if (animationFinish) {
 60             int action = ev.getAction();
 61             switch (action) {
 62             case MotionEvent.ACTION_DOWN:
 63                 y = ev.getY();
 64                 break;
 65             case MotionEvent.ACTION_UP:
 66                 y = 0;
 67                 if (isNeedAnimation()) {
 68                     animation();
 69                 }
 70                 break;
 71             case MotionEvent.ACTION_MOVE:
 72                 final float preY = y == 0 ? ev.getY() : y;
 73                 float nowY = ev.getY();
 74                 int deltaY = (int) (preY - nowY);
 75 
 76                 y = nowY;
 77                 // 当滚动到最上或者最下时就不会再滚动,这时移动布局
 78                 if (isNeedMove(deltaY)) {
 79                     if (normal.isEmpty()) {
 80                         // 保存正常的布局位置
 81                         normal.set(getLeft(), getTop(), getRight(), getBottom());
 82                     }
 83                     // 移动布局
 84                     layout(getLeft(), getTop() - deltaY / 2, getRight(), getBottom() - deltaY / 2);
 85                 }
 86                 break;
 87             default:
 88                 break;
 89             }
 90         }
 91     }
 92 
 93     // 开启动画移动
 94     public void animation() {
 95         // 开启移动动画
 96         TranslateAnimation ta = new TranslateAnimation(0, 0, 0, normal.top - getTop());
 97         ta.setDuration(200);
 98         ta.setAnimationListener(new AnimationListener() {
 99             @Override
100             public void onAnimationStart(Animation animation) {
101                 animationFinish = false;
102 
103             }
104 
105             @Override
106             public void onAnimationRepeat(Animation animation) {
107 
108             }
109 
110             @Override
111             public void onAnimationEnd(Animation animation) {
112                 clearAnimation();
113                 // 设置回到正常的布局位置
114                 layout(normal.left, normal.top, normal.right, normal.bottom);
115                 normal.setEmpty();
116                 animationFinish = true;
117             }
118         });
119         startAnimation(ta);
120     }
121 
122     // 是否需要开启动画
123     public boolean isNeedAnimation() {
124         return !normal.isEmpty();
125     }
126 
127     // 是否需要移动布局
128     public boolean isNeedMove(float deltaY) {
129         if (overScrolled && getChildCount() > 0) {
130             if (getLastVisiblePosition() == getCount() - 1 && deltaY > 0) {
131                 return true;
132             }
133             if (getFirstVisiblePosition() == 0 && deltaY < 0) {
134                 return true;
135             }
136         }
137         return false;
138     }
139 }

 

测试代码:

 1 public class MainActivity extends Activity {
 2     ElasticListView listView;
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7         
 8         listView = (ElasticListView) findViewById(R.id.listview);
 9         
10         String[] listValues = new String[20];
11         for (int i=0;i<listValues.length;i++) {
12             listValues[i] = "TextView" + i;
13         }
14         listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listValues));
15     }
16 }

 

 1 public class MainActivity extends Activity {
 2     ElasticListView listView;
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7         
 8         listView = (ElasticListView) findViewById(R.id.listview);
 9         
10         String[] listValues = new String[20];
11         for (int i=0;i<listValues.length;i++) {
12             listValues[i] = "TextView" + i;
13         }
14         listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listValues));
15     }
16 }

 

posted @ 2014-12-08 23:35  perfect亮  阅读(393)  评论(0编辑  收藏  举报