带阻尼效果的horizontalscrollview

要实现的效果就是HorizontalScrollView中最上方有一个阻尼效果,当下拉的时候,产生一种被拉伸的效果,松手后恢复原样,就像弹簧一样。

如果实现这种效果,需要重写HorizontalScrollView:

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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
/**
* Author: wangchao
* Time: 2018/4/7
* Description: This is 带阻尼效果的水平滑动控件
*/
public class HorizontalFeatureScrollView extends HorizontalScrollView {

private View inner;
private float x;
private Rect normal = new Rect();
private boolean isCount = false;
private boolean isMoveing = false;
private int initLeft;
private int left;
private View views;

public HorizontalFeatureScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}

/**
* Based on the XML generated view work done.
* The function in the creation of the view of the last call.
* after all sub-view has been added.
* Even if the sub-class covered the onFinishInflate method.
* it should also call the parent class method to make the method to be implemented.
*/
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
inner = getChildAt(0);
}
}

/**
* Touch event handling
**/
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (inner != null) {
commOnTouchEvent(ev);
}
return super.onTouchEvent(ev);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
if (views != null) {
//Views.getDrawer().closeDrawers();
}
}
return super.onInterceptTouchEvent(ev);
}

/**
* Slide event (let the speed of sliding into the original 1/2)
*/
@Override
public void fling(int velocityY) {
super.fling(velocityY / 2);
}

/***
* Touch the event
*
* @param ev
*/
public void commOnTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
break;

case MotionEvent.ACTION_UP:
isMoveing = false;
// Fingers loose
if (isNeedAnimation()) {
animation();
}

break;
/**Excluding the first mobile calculation.
* because the first time can not know the y coordinates.
* in MotionEvent.ACTION_DOWN not get.
* because this time is MyScrollView touch event passed to the LIstView child item above.
* So from the second calculation But we also have to initialize.
* that is. the first time to move the sliding distance to 0.
* After the record is accurate on the normal implementation.
*/
case MotionEvent.ACTION_MOVE:
final float preX = x;// When the y coordinate is pressed
float nowX = ev.getX();// Always y-coordinate
int deltaX = (int) (nowX - preX);// Slide distance
if (!isCount) {
deltaX = 0; // Here to 0.
}
// When the scroll to the top or the most when it will not scroll, then move the layout.
isNeedMove();

if (isMoveing) {
// Initialize the head rectangle
if (normal.isEmpty()) {
// Save the normal layout position
normal.set(inner.getLeft(), inner.getTop(),
inner.getRight(), inner.getBottom());
}

// Move the layout
inner.layout(inner.getLeft() + deltaX / 3, inner.getTop(),
inner.getRight() + deltaX / 3, inner.getBottom());

left += (deltaX / 6);
}

isCount = true;
x = nowX;
break;

default:
break;

}
}

/**
* Retract animation
*/
public void animation() {
TranslateAnimation taa = new TranslateAnimation(0, 0, left + 200,
initLeft + 200);
taa.setDuration(200);
TranslateAnimation ta = null;
// Turn on moving animation
ta = new TranslateAnimation(inner.getLeft(), normal.left, 0, 0);
ta.setDuration(200);
inner.startAnimation(ta);
// Set back to the normal layout position
inner.layout(normal.left, normal.top, normal.right, normal.bottom);
normal.setEmpty();

isCount = false;
x = 0;// Fingers loose to 0..

}

// Whether you need to turn on animation
public boolean isNeedAnimation() {
return !normal.isEmpty();
}

/***
* Whether you need to move the layout inner.getMeasuredHeight (): get the total height of the control
* <p>
* GetHeight (): Get the height of the screen.
*
* @return
*/
public void isNeedMove() {
int scrollY = getScrollY();
if (scrollY == 0) {
isMoveing = true;
}
}

public void setContextView(View view) {
this.views = view;
}
}

这样就可以实现效果了。