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

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

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

国际惯例,效果图:

主要代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  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. }  


测试代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  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. }  
[html] view plaincopy在CODE上查看代码片派生到我的代码片
 
    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.     }  
原文地址:https://www.cnblogs.com/Free-Thinker/p/4126088.html