Skip to content

Commit 7bf9822

Browse files
authored
Update README.md
1 parent d5a865f commit 7bf9822

File tree

1 file changed

+167
-162
lines changed

1 file changed

+167
-162
lines changed

README.md

+167-162
Original file line numberDiff line numberDiff line change
@@ -1,163 +1,168 @@
11
#zoomheaderview
2-
3-
4-
![image](https://github.com/githubwing/ZoomHeader/raw/master/img.gif)
5-
6-
7-
8-
9-
## [下载体验](https://github.com/githubwing/ZoomHeader/raw/master/app-debug.apk)
10-
11-
这是一个模仿饿了么详情页的例子。
12-
13-
讲述了如何实现。具体祥见源码。
14-
15-
16-
### 他是一个Activity还是两个?
17-
18-
相信你肯定有这样的疑问,答案是一个。你看到的中间imageview是viewpager。在Viewpager上面是一个透明的View。当然,这个Activity的背景也是透明的。
19-
20-
### 实现思路
21-
22-
我使用CoordinatorLayout+Behavior实现的。说实话,Behavior真心强大。。
23-
24-
25-
### viewpager+头部
26-
27-
整个实现的思路是这样的。整体布局从上到下依次是:
28-
29-
* 透明View
30-
* viewpager
31-
* RecyclerView
32-
33-
34-
其中透明View和Viewpager 合并成一个自定义的Header。当这个Header上移的时候,图片放大,并且RecyclerView联动上衣,从透明转向并且不透明。
35-
36-
37-
所以首先要定制一个透明的可移动的HeaderView。
38-
39-
在onTouchEvent处理一下手势。。
40-
41-
```java
42-
@Override public boolean onTouchEvent(MotionEvent ev) {
43-
switch (ev.getAction()) {
44-
case MotionEvent.ACTION_DOWN:
45-
return true;
46-
case MotionEvent.ACTION_MOVE:
47-
if(上下移动到阀值){
48-
展开为详情()
49-
}else if(上下滑动到阀值,恢复viewpager){
50-
}else if(下滑,则关闭Activity)
51-
```
52-
53-
将header分为三种状态:
54-
55-
* 上移。则展开为详情页。
56-
* 下移,则恢复为viewpager。
57-
* 再下移,则finish Activity
58-
59-
60-
在上移的过程中,遇到了一点小挑战,这里分享下:
61-
62-
上移的过程中,图片需要放大。但是在做的过程中,不能使用LayoutParams实现。这里就关系到一些动画的小细节。
63-
64-
**动画使用LayoutParams实现是一个禁忌。他会导致不停requestLayout,从而影响UI性能。**
65-
66-
所以这里我的一个解法就是,我放大图片,不是真正的改变ImageView大小,而是去Scale图片。即使看起来变大了,他的View真正大小也不会变。
67-
68-
所以,有一句话叫做**真亦是假、假亦是真** 真真假假,你又何必当真呢?动画效果只要遵循这句话,基本上都是可以实现的。你所看到的效果都是假的。都是障眼法。View变大不是真正的变大。View悬浮不是真正的悬浮(有可能是显隐)。就像变魔术一样。。其实很简单。
69-
70-
接下来又遇到问题了。图片放大了,文字如何对齐? 文字的位置当然也不能真正改变。所以这里使用TranslationX实现。在图片放大的过程中,使用scale的系数,与两个端点值进行一个线性变化计算。主要文字对齐代码如下:
71-
72-
```java
73-
bottom.offsetLeftAndRight(
74-
(int) (target.getWidth() / 2 - target.getWidth() * (1 + progress) / 2
75-
+ MarginConfig.MARGIN_LEFT_RIGHT - bottom.getX()));
76-
77-
```
78-
79-
第二个点。就是在图片放大过程中,底部文字和按钮左右padding不能变。这也是我没有封装成一个拿来就用的View的原因(其实还是水平不够)。因为这些空间需要全部按照上方的方法进行动态计算。。所以也是比较坑爹的。。
80-
81-
### ViewPager
82-
83-
拿了网上一个画廊的效果。直接
84-
85-
```java
86-
setPageTransformer(true, new ZoomOutPageTransformer());
87-
```
88-
89-
这里注意,需要改变一下view的绘制顺序,保证当前view是最后绘制处于最上层
90-
91-
```java
92-
/改变系统绘制顺序
93-
@Override protected int getChildDrawingOrder(int childCount, int i) {
94-
95-
int position = getCurrentItem();
96-
if(position<0){
97-
return i;
98-
}else{
99-
if(i == childCount - 1){//这是最后一个需要刷新的item
100-
if(position>i){
101-
position=i;
102-
}
103-
return position;
104-
}
105-
if(i == position){//这是原本要在最后一个刷新的item
106-
return childCount - 1;
107-
}
108-
}
109-
return i;
110-
}
111-
}
112-
113-
```
114-
115-
### RecyclerView
116-
117-
RecyclerView最开始是完全透明的。并且跟随HeaderView上移而上移,在上移的过程中渐渐显示出来。 需要监听RecyclerView滚动,当RecyclerView滚动到顶部的时候。告知Header,该恢复最初原样了。
118-
119-
```java
120-
@Override
121-
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target,
122-
float velocityX, float velocityY, boolean consumed) {
123-
124-
//向下Fling并且到顶部
125-
if (velocityY < 0 && ((RecyclerView) target).getChildAt(0).getY() == 0) {
126-
mDependency.restore(mDependency.getY());
127-
}
128-
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
129-
}
130-
131-
@Override
132-
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target,
133-
int dx, int dy, int[] consumed) {
134-
135-
//如果在顶部
136-
if (((RecyclerView) target).getChildAt(0).getY() == 0) {
137-
//向下滑动
138-
if (dy < 0) {
139-
mDependency.setY(mDependency.getY() - dy);
140-
//小于阀值
141-
if (mDependency.getY() < 500) {
142-
mDependency.restore(mDependency.getY());
143-
}
144-
}
145-
}
146-
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
147-
}
148-
}
149-
```
150-
151-
152-
### Behavior
153-
154-
让header和RecyclerView关联起来的就是Behavior了。Behavior之前写过几篇介绍过了,这里就不再啰嗦。
155-
156-
denpendcy为HeaderView。并且监听RecyclerView的滑动。
157-
158-
159-
具体的细节还是看源码吧~
160-
161-
如果你觉得还不错,欢迎Star
162-
欢迎加入我的qq群: 425983695
163-
2+
3+
4+
![image](https://github.com/githubwing/ZoomHeader/raw/master/img.gif)
5+
6+
7+
8+
9+
## [下载体验](https://github.com/githubwing/ZoomHeader/raw/master/app-debug.apk)
10+
11+
12+
**先吐槽下饿了么。不提示左右可以滑动。我还是无意中发现的。不提示我怎么知道可以滑动??**
13+
14+
15+
这是一个模仿饿了么详情页的例子。
16+
17+
讲述了如何实现。具体祥见源码。
18+
19+
20+
21+
### 他是一个Activity还是两个?
22+
23+
相信你肯定有这样的疑问,答案是一个。你看到的中间imageview是viewpager。在Viewpager上面是一个透明的View。当然,这个Activity的背景也是透明的。
24+
25+
### 实现思路
26+
27+
我使用CoordinatorLayout+Behavior实现的。说实话,Behavior真心强大。。
28+
29+
30+
### viewpager+头部
31+
32+
整个实现的思路是这样的。整体布局从上到下依次是:
33+
34+
* 透明View
35+
* viewpager
36+
* RecyclerView
37+
38+
39+
其中透明View和Viewpager 合并成一个自定义的Header。当这个Header上移的时候,图片放大,并且RecyclerView联动上衣,从透明转向并且不透明。
40+
41+
42+
所以首先要定制一个透明的可移动的HeaderView。
43+
44+
在onTouchEvent处理一下手势。。
45+
46+
```java
47+
@Override public boolean onTouchEvent(MotionEvent ev) {
48+
switch (ev.getAction()) {
49+
case MotionEvent.ACTION_DOWN:
50+
return true;
51+
case MotionEvent.ACTION_MOVE:
52+
if(上下移动到阀值){
53+
展开为详情()
54+
}else if(上下滑动到阀值,恢复viewpager){
55+
}else if(下滑,则关闭Activity)
56+
```
57+
58+
将header分为三种状态:
59+
60+
* 上移。则展开为详情页。
61+
* 下移,则恢复为viewpager。
62+
* 再下移,则finish Activity
63+
64+
65+
在上移的过程中,遇到了一点小挑战,这里分享下:
66+
67+
上移的过程中,图片需要放大。但是在做的过程中,不能使用LayoutParams实现。这里就关系到一些动画的小细节。
68+
69+
**动画使用LayoutParams实现是一个禁忌。他会导致不停requestLayout,从而影响UI性能。**
70+
71+
所以这里我的一个解法就是,我放大图片,不是真正的改变ImageView大小,而是去Scale图片。即使看起来变大了,他的View真正大小也不会变。
72+
73+
所以,有一句话叫做**真亦是假、假亦是真** 真真假假,你又何必当真呢?动画效果只要遵循这句话,基本上都是可以实现的。你所看到的效果都是假的。都是障眼法。View变大不是真正的变大。View悬浮不是真正的悬浮(有可能是显隐)。就像变魔术一样。。其实很简单。
74+
75+
接下来又遇到问题了。图片放大了,文字如何对齐? 文字的位置当然也不能真正改变。所以这里使用TranslationX实现。在图片放大的过程中,使用scale的系数,与两个端点值进行一个线性变化计算。主要文字对齐代码如下:
76+
77+
```java
78+
bottom.offsetLeftAndRight(
79+
(int) (target.getWidth() / 2 - target.getWidth() * (1 + progress) / 2
80+
+ MarginConfig.MARGIN_LEFT_RIGHT - bottom.getX()));
81+
82+
```
83+
84+
第二个点。就是在图片放大过程中,底部文字和按钮左右padding不能变。这也是我没有封装成一个拿来就用的View的原因(其实还是水平不够)。因为这些空间需要全部按照上方的方法进行动态计算。。所以也是比较坑爹的。。
85+
86+
### ViewPager
87+
88+
拿了网上一个画廊的效果。直接
89+
90+
```java
91+
setPageTransformer(true, new ZoomOutPageTransformer());
92+
```
93+
94+
这里注意,需要改变一下view的绘制顺序,保证当前view是最后绘制处于最上层
95+
96+
```java
97+
/改变系统绘制顺序
98+
@Override protected int getChildDrawingOrder(int childCount, int i) {
99+
100+
int position = getCurrentItem();
101+
if(position<0){
102+
return i;
103+
}else{
104+
if(i == childCount - 1){//这是最后一个需要刷新的item
105+
if(position>i){
106+
position=i;
107+
}
108+
return position;
109+
}
110+
if(i == position){//这是原本要在最后一个刷新的item
111+
return childCount - 1;
112+
}
113+
}
114+
return i;
115+
}
116+
}
117+
118+
```
119+
120+
### RecyclerView
121+
122+
RecyclerView最开始是完全透明的。并且跟随HeaderView上移而上移,在上移的过程中渐渐显示出来。 需要监听RecyclerView滚动,当RecyclerView滚动到顶部的时候。告知Header,该恢复最初原样了。
123+
124+
```java
125+
@Override
126+
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target,
127+
float velocityX, float velocityY, boolean consumed) {
128+
129+
//向下Fling并且到顶部
130+
if (velocityY < 0 && ((RecyclerView) target).getChildAt(0).getY() == 0) {
131+
mDependency.restore(mDependency.getY());
132+
}
133+
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
134+
}
135+
136+
@Override
137+
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target,
138+
int dx, int dy, int[] consumed) {
139+
140+
//如果在顶部
141+
if (((RecyclerView) target).getChildAt(0).getY() == 0) {
142+
//向下滑动
143+
if (dy < 0) {
144+
mDependency.setY(mDependency.getY() - dy);
145+
//小于阀值
146+
if (mDependency.getY() < 500) {
147+
mDependency.restore(mDependency.getY());
148+
}
149+
}
150+
}
151+
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
152+
}
153+
}
154+
```
155+
156+
157+
### Behavior
158+
159+
让header和RecyclerView关联起来的就是Behavior了。Behavior之前写过几篇介绍过了,这里就不再啰嗦。
160+
161+
denpendcy为HeaderView。并且监听RecyclerView的滑动。
162+
163+
164+
具体的细节还是看源码吧~
165+
166+
如果你觉得还不错,欢迎Star
167+
欢迎加入我的qq群: 425983695
168+

0 commit comments

Comments
 (0)