Skip to content

Commit 803924b

Browse files
author
csnowstack
committed
filing 到头的时候展开 head
1 parent 904970d commit 803924b

File tree

8 files changed

+188
-44
lines changed

8 files changed

+188
-44
lines changed

README.md

Lines changed: 65 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
### 简介
44

5+
[项目地址](https://github.com/CSnowStack/BehaviorDemo)
6+
57
#### 建议
68
请先阅读[这篇文章](http://www.jianshu.com/p/f7989a2a3ec2)
79
> 好多东西抄自这里
@@ -17,13 +19,11 @@
1719

1820
![实现的效果](https://github.com/CSnowStack/BehaviorDemo/blob/master/img/c.gif)
1921

20-
[项目地址](https://github.com/CSnowStack/BehaviorDemo)
2122

22-
> 一些细节没有实现 ,见谅,录制的gif效果也不太好 :-(
2323

2424

25-
### TODO
26-
- 快速滑动会产生问题.....
25+
> 一些细节没有实现 ,见谅,录制的gif效果也不太好 :-(
26+
2727

2828
### 实现
2929

@@ -50,42 +50,79 @@
5050

5151
- `ToolBarIcon` 跟随`BGContent` ,根据`BGContent`移动的比例修改图标的`Alpha`
5252

53-
5453
#### 部分代码
5554

5655
```java
5756
//TabBehavior
58-
@Override
5957
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
6058
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
61-
//只要开始拦截,就需要把所有Scroll事件消费掉
62-
consumed[1]=dy;
63-
int distance=-dy/2;//降低移动的速度
64-
mUp=dy>0;
65-
66-
if(child.getTranslationY()+distance<-mMaxDistance){
67-
distance=-mMaxDistance;
68-
}else if(child.getTranslationY()+distance>0){
69-
distance=0;
70-
}else {
71-
distance= (int) (child.getTranslationY()+distance);
59+
60+
if(isChildRequestScroll(child.getTranslationY())){//如果list需要滑动这边就不动
61+
consumed[1]=0;
62+
return;
63+
}
64+
65+
consumed[1]=dy;//全部消耗
66+
int distance = -dy / 2;//降低移动的速度
67+
mUp = dy > 0;
68+
69+
if (child.getTranslationY() + distance < -mMaxDistance) {
70+
distance = -mMaxDistance;
71+
} else if (child.getTranslationY() + distance > 0) {
72+
distance = 0;
73+
} else {
74+
distance = (int) (child.getTranslationY() + distance);
7275
}
7376
child.setTranslationY(distance);
7477
}
7578

76-
//ListBehavior
79+
/**
80+
* Child是否需要滑动
81+
*/
82+
private boolean isChildRequestScroll(float translationY) {
83+
return (translationY == -mMaxDistance &&//在顶部
84+
mViewPager.getAdapter() != null && //有适配器
85+
mViewPager.getAdapter().getCount() > 0 &&//有item
86+
mViewPager.getAdapter() instanceof IsChildRequestScrollListener && //实现了
87+
((IsChildRequestScrollListener) mViewPager.getAdapter()).requestScroll()//需要滑动
88+
);
89+
}
90+
91+
92+
//设置 listener 检测是否需要展开
7793
@Override
78-
int getScrollRange(View v) {
79-
if (isDependOn(v)) {
80-
return -mHeightToolbar;
81-
} else {
82-
return super.getScrollRange(v);
83-
}
94+
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
95+
mControlChange=true;
96+
97+
if(mViewPager.getAdapter() != null && //有适配器
98+
mViewPager.getAdapter().getCount() > 0 &&//有item
99+
mViewPager.getAdapter() instanceof SupportNeedExpendListener&&
100+
((SupportNeedExpendListener) mViewPager.getAdapter()).getNeedExpendListener()==null){
101+
((SupportNeedExpendListener) mViewPager.getAdapter()).setNeedExpendListener(this);
102+
}
103+
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
84104
}
85-
// HeaderScrollingViewBehavior$onMeasure 所以要返回 - mHeightToolbar
86-
final int height = availableHeight - header.getMeasuredHeight()
87-
+ getScrollRange(header);
88105

106+
/**
107+
* list fling到头的时候 展开
108+
*/
109+
@Override
110+
public void needExpand() {
111+
if(!mControlChange){//如果是手指在控制就不管
112+
mValueAnimator.setDuration(500);
113+
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
114+
@Override
115+
public void onAnimationUpdate(ValueAnimator animation) {
116+
mTab.setTranslationY((animation.getAnimatedFraction()-1)*mMaxDistance);
117+
}
118+
});
119+
mValueAnimator.start();
120+
}
121+
}
89122
```
90123

91-
>代码是蛮简单的 ,直接看项目即可,就那几行代码
124+
>代码是蛮简单的 ,直接看项目即可,就那几行代码, 又加看点功能 耦合度变高了的感觉欢迎 Star,提 issue 还有PR
125+
126+
127+
### TODO
128+
- 在向上fling的过程中,向下滑,会出现错乱的情况 :-(

app/src/main/java/cq/behaviordemo/ItemFragment.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
import android.view.ViewGroup;
1111

1212
import cq.behaviordemo.adapter.FriendInfoAdapter;
13+
import cq.behaviordemo.listener.IsChildRequestScrollListener;
14+
import cq.behaviordemo.listener.NeedExpandListener;
15+
import cq.behaviordemo.listener.SupportNeedExpendListener;
1316

1417
/**
1518
* Created by cqll on 2016/9/30.
1619
*/
1720

18-
public class ItemFragment extends Fragment implements IsChildRequestScrollListener{
21+
public class ItemFragment extends Fragment implements IsChildRequestScrollListener ,SupportNeedExpendListener{
1922

2023
private RecyclerView mRecyclerView;
21-
24+
private NeedExpandListener mNeedExpandListener;
2225
public static ItemFragment newInstance() {
2326

2427
Bundle args = new Bundle();
@@ -39,6 +42,21 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
3942
private void initView() {
4043
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
4144
mRecyclerView.setAdapter(new FriendInfoAdapter());
45+
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
46+
@Override
47+
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
48+
super.onScrollStateChanged(recyclerView, newState);
49+
}
50+
51+
@Override
52+
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
53+
super.onScrolled(recyclerView, dx, dy);
54+
if(dy<0&&((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition()==0){
55+
if(mNeedExpandListener!=null)
56+
mNeedExpandListener.needExpand();
57+
}
58+
}
59+
});
4260
}
4361

4462

@@ -50,4 +68,15 @@ public boolean requestScroll() {
5068
mRecyclerView.getAdapter().getItemCount()>0&&
5169
((LinearLayoutManager)mRecyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition()==0);
5270
}
71+
72+
73+
@Override
74+
public void setNeedExpendListener(NeedExpandListener listener) {
75+
mNeedExpandListener=listener;
76+
}
77+
78+
@Override
79+
public NeedExpandListener getNeedExpendListener() {
80+
return mNeedExpandListener;
81+
}
5382
}

app/src/main/java/cq/behaviordemo/adapter/ItemAdapter.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,33 @@
99
import java.util.ArrayList;
1010
import java.util.List;
1111

12-
import cq.behaviordemo.IsChildRequestScrollListener;
12+
import cq.behaviordemo.listener.IsChildRequestScrollListener;
1313
import cq.behaviordemo.ItemFragment;
14+
import cq.behaviordemo.listener.NeedExpandListener;
15+
import cq.behaviordemo.listener.SupportNeedExpendListener;
1416

1517
/**
1618
* Created by cqll on 2016/12/15.
1719
*/
1820

19-
public class ItemAdapter extends FragmentStatePagerAdapter implements IsChildRequestScrollListener{
21+
public class ItemAdapter extends FragmentStatePagerAdapter implements IsChildRequestScrollListener,SupportNeedExpendListener{
2022
private String [] titles={"MEDIA","ABOUT","REVIEWS"};
2123
private WeakReference<ViewPager> mViewPager;//也许有点用
2224
private List<ItemFragment> mFragments;
25+
private NeedExpandListener mNeedExpandListener;
2326
public ItemAdapter(FragmentManager fm) {
2427
this(fm,null);
2528
}
2629

2730
public ItemAdapter(FragmentManager fm, ViewPager viewPager) {
2831
super(fm);
2932
mViewPager = new WeakReference<ViewPager>(viewPager);
33+
3034
mFragments=new ArrayList<ItemFragment>();
3135
mFragments.add(ItemFragment.newInstance());
3236
mFragments.add(ItemFragment.newInstance());
3337
mFragments.add(ItemFragment.newInstance());
38+
fillListener();
3439
}
3540

3641
@Override
@@ -61,4 +66,25 @@ public boolean requestScroll() {
6166

6267
return false;
6368
}
69+
70+
@Override
71+
public void setNeedExpendListener(NeedExpandListener listener) {
72+
mNeedExpandListener=listener;
73+
fillListener();
74+
}
75+
76+
@Override
77+
public NeedExpandListener getNeedExpendListener() {
78+
return mNeedExpandListener;
79+
}
80+
81+
private void fillListener(){
82+
if(mFragments.size()>0){
83+
for(Fragment fragment:mFragments){
84+
if(fragment instanceof SupportNeedExpendListener &&((SupportNeedExpendListener)fragment).getNeedExpendListener()==null){
85+
((SupportNeedExpendListener)fragment).setNeedExpendListener(mNeedExpandListener);
86+
}
87+
}
88+
}
89+
}
6490
}

app/src/main/java/cq/behaviordemo/behavior/TabBehavior.java

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,22 @@
99
import android.view.View;
1010

1111
import cq.behaviordemo.Constants;
12-
import cq.behaviordemo.IsChildRequestScrollListener;
1312
import cq.behaviordemo.R;
13+
import cq.behaviordemo.listener.IsChildRequestScrollListener;
14+
import cq.behaviordemo.listener.NeedExpandListener;
15+
import cq.behaviordemo.listener.SupportNeedExpendListener;
1416

1517
/**
1618
* Created by cqll on 2016/12/9.
1719
*/
1820

19-
public class TabBehavior extends CoordinatorLayout.Behavior {
21+
public class TabBehavior extends CoordinatorLayout.Behavior implements NeedExpandListener {
2022
private int mHeightToolbar, mMaxDistance, mEditorPadding;
2123
private Context mContext;
22-
private boolean mUp/*向上滑动,还是向下滑动*/;
24+
private boolean mUp/*向上滑动,还是向下滑动*/,mControlChange/*手指控制的滑动*/;
2325
private ValueAnimator mValueAnimator;
2426
private ViewPager mViewPager;
25-
27+
private View mTab;
2628
public TabBehavior() {
2729
}
2830

@@ -33,8 +35,6 @@ public TabBehavior(Context context, AttributeSet attrs) {
3335
mEditorPadding = context.getResources().getDimensionPixelOffset(R.dimen.editor_padding);
3436

3537
mValueAnimator = ValueAnimator.ofFloat(0, 1);
36-
37-
3838
}
3939

4040

@@ -48,6 +48,7 @@ public TabBehavior(Context context, AttributeSet attrs) {
4848
@Override
4949
public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) {
5050
parent.onLayoutChild(child, layoutDirection);
51+
mTab=child;
5152
mViewPager = (ViewPager) parent.findViewById(R.id.viewpager);
5253
mMaxDistance = (int) (child.getWidth() * Constants.FRACTION_WIDTH_BGCONTENT * 0.64f + mContext.getResources().getDimensionPixelOffset(R.dimen.img_icon_height_start) / 2 + child.getWidth() * Constants.FRACTION_PADDING + mEditorPadding);
5354
child.offsetTopAndBottom(mMaxDistance + mHeightToolbar);
@@ -57,8 +58,15 @@ public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDir
5758

5859
@Override
5960
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
61+
mControlChange=true;
62+
63+
if(mViewPager.getAdapter() != null && //有适配器
64+
mViewPager.getAdapter().getCount() > 0 &&//有item
65+
mViewPager.getAdapter() instanceof SupportNeedExpendListener&&
66+
((SupportNeedExpendListener) mViewPager.getAdapter()).getNeedExpendListener()==null){
67+
((SupportNeedExpendListener) mViewPager.getAdapter()).setNeedExpendListener(this);
68+
}
6069
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
61-
6270
}
6371

6472

@@ -69,11 +77,11 @@ public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View chi
6977
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
7078
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed);
7179

72-
if(isChildRequestScroll(child)){//如果list需要滑动这边就不动
80+
if(isChildRequestScroll(child.getTranslationY())){//如果list需要滑动这边就不动
7381
consumed[1]=0;
7482
return;
7583
}
76-
//只要开始拦截,就需要把所有Scroll事件消费掉
84+
7785
consumed[1]=dy;//全部消耗
7886
int distance = -dy / 2;//降低移动的速度
7987
mUp = dy > 0;
@@ -92,6 +100,7 @@ public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, V
92100
@Override
93101
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) {
94102
super.onStopNestedScroll(coordinatorLayout, child, target);
103+
mControlChange=false;
95104
float translationY = child.getTranslationY();
96105
if (Math.abs(translationY) == mMaxDistance || translationY == 0) {
97106
return;
@@ -131,12 +140,33 @@ public void onAnimationUpdate(ValueAnimator animation) {
131140
}
132141

133142

134-
private boolean isChildRequestScroll(View tab) {
135-
return (tab.getTranslationY() == -mMaxDistance &&//在顶部
143+
/**
144+
* Child是否需要滑动
145+
*/
146+
private boolean isChildRequestScroll(float translationY) {
147+
return (translationY == -mMaxDistance &&//在顶部
136148
mViewPager.getAdapter() != null && //有适配器
137149
mViewPager.getAdapter().getCount() > 0 &&//有item
138150
mViewPager.getAdapter() instanceof IsChildRequestScrollListener && //实现了
139151
((IsChildRequestScrollListener) mViewPager.getAdapter()).requestScroll()//需要滑动
140152
);
141153
}
154+
155+
156+
/**
157+
* list fling到头的时候 展开
158+
*/
159+
@Override
160+
public void needExpand() {
161+
if(!mControlChange){
162+
mValueAnimator.setDuration(500);
163+
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
164+
@Override
165+
public void onAnimationUpdate(ValueAnimator animation) {
166+
mTab.setTranslationY((animation.getAnimatedFraction()-1)*mMaxDistance);
167+
}
168+
});
169+
mValueAnimator.start();
170+
}
171+
}
142172
}

app/src/main/java/cq/behaviordemo/IsChildRequestScrollListener.java renamed to app/src/main/java/cq/behaviordemo/listener/IsChildRequestScrollListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package cq.behaviordemo;
1+
package cq.behaviordemo.listener;
22

33
/**
44
* Created by cqll on 2016/12/15.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package cq.behaviordemo.listener;
2+
3+
/**
4+
* Created by cqll on 2016/12/15.
5+
* list可以滑动的时候,向下滑,然后松开手指,list滑到顶的时候触发
6+
* 通知 tab 展开头部
7+
*/
8+
9+
public interface NeedExpandListener {
10+
void needExpand();
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package cq.behaviordemo.listener;
2+
3+
/**
4+
* Created by cqll on 2016/12/15.
5+
* 是否支持 展开
6+
*/
7+
8+
public interface SupportNeedExpendListener {
9+
void setNeedExpendListener(NeedExpandListener listener);
10+
NeedExpandListener getNeedExpendListener();
11+
}

img/c.gif

274 KB
Loading

0 commit comments

Comments
 (0)