【转】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 }