Android 自定义弹性ListView控件实例代码(三种方法)

时间:2022-05-26 09:50:29

关于在Android中实现ListView的弹性效果,有很多不同的方法,网上一搜,也有很多,下面贴出在项目中经常用到的两种实现ListView弹性效果的方法(基本上拿来就可以用),供大家参考:

弹性ListView

第一种方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.ListView;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* Created by Noah on 2016/1/16.
*/
public class BounceListView extends ListView {
private static final float MAX_Y_OVERSCROLL_DISTANCE = 200;
private float mMaxYOverscrollDistance;
public BounceListView(Context context) {
this(context, null);
}
public BounceListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BounceListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initBounceListView();
}
private void initBounceListView(){
final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
final float density = metrics.density;
mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);
}
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, (int)mMaxYOverscrollDistance, isTouchEvent);
}
/**
* 设置本App所有的ListView弹性粒度
* @param ctx
* @param size
* @return
*/
public boolean configGlobalMaxOverScrollDistance(Context ctx,int size)
{
try {
final DisplayMetrics metrics = ctx.getResources().getDisplayMetrics();
final float density = metrics.density;
int value = (int) (density * size);
mMaxYOverscrollDistance = value;
ViewConfiguration config = ViewConfiguration.get(ctx);
Field mOverscrollDistance = ViewConfiguration.class.getDeclaredField("mOverscrollDistance");
if(!mOverscrollDistance.isAccessible() || !Modifier.isPublic(mOverscrollDistance.getModifiers()))
{
mOverscrollDistance.setAccessible(true);
}
mOverscrollDistance.setInt(config,value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}

第二种比较简单,好容易理解,只是动态改变了ListView在Y轴上的可移动距离,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.ListView;
/**
* 弹性ListView。
* @author E
*/
public class FlexiListView extends ListView{
//初始可拉动Y轴方向距离
private static final int MAX_Y_OVERSCROLL_DISTANCE = 100;
//上下文环境
private Context mContext;
//实际可上下拉动Y轴上的距离
private int mMaxYOverscrollDistance;
public FlexiListView(Context context){
super(context);
mContext = context;
initBounceListView();
}
public FlexiListView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
initBounceListView();
}
public FlexiListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
initBounceListView();
}
private void initBounceListView(){
final DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
final float density = metrics.density;
mMaxYOverscrollDistance = (int) (density * MAX_Y_OVERSCROLL_DISTANCE);
}
@Override
protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX,
int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
//实现的本质就是在这里动态改变了maxOverScrollY的值
return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, mMaxYOverscrollDistance, isTouchEvent);
}
}

第三种方法,结合了手势来实现ListView的弹性效果,这里可以根据手势来进行更多的扩展,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ListView;
/**
* 具有弹性效果的ListView。主要是实现父类dispatchTouchEvent方法和OnGestureListener中onScroll方法。
* @author E
*/
public class FlexibleListView extends ListView implements OnGestureListener{
private Context context = null;
private boolean outBound = false;
private int distance;
private int firstOut;
public FlexibleListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
public FlexibleListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
public FlexibleListView(Context context) {
super(context);
this.context = context;
}
GestureDetector lisGestureDetector = new GestureDetector(context, this);
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int act = event.getAction();
if ((act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_CANCEL)
&& outBound) {
outBound = false;
// scroll back
}
if (!lisGestureDetector.onTouchEvent(event)) {
outBound = false;
} else {
outBound = true;
}
Rect rect = new Rect();
getLocalVisibleRect(rect);
TranslateAnimation am = new TranslateAnimation( 0, 0, -rect.top, 0);
am.setDuration(300);
startAnimation(am);
scrollTo(0, 0);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
int firstPos = getFirstVisiblePosition();
int lastPos = getLastVisiblePosition();
int itemCount = getCount();
// outbound Top
if (outBound && firstPos != 0 && lastPos != (itemCount - 1)) {
scrollTo(0, 0);
return false;
}
View firstView = getChildAt(firstPos);
if (!outBound)
firstOut = (int) e2.getRawY();
if (firstView != null&& (outBound || (firstPos == 0
&& firstView.getTop() == 0 && distanceY < 0))) {
// Record the length of each slide
distance = firstOut - (int) e2.getRawY();
scrollTo(0, distance / 2);
return true;
}
// outbound Bottom
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
}

以上给大家分享了几种比较常用的方法,服务器之家小编整理出来的,希望对大家有所帮助。