Behavior的demo——粗仿天猫详情页效果
来源:互联网 发布:淘宝怎么秒杀 编辑:程序博客网 时间:2024/05/22 06:33
效果
整个内容区域分为上下两部分,当将上部分内容拉到底部时,再拉动会将下面一部分内容拉出来,并且在松手时根据拉动的距离判断是回弹还是拉出来。在下部分时同样,拉动到顶部后继续下拉会将上部分拉出来。思路
思路一
可以将上部分写成带有上拉功能的控件,根据拉动的距离将下部分在垂直方向上进行移动,从而达到模拟上拉的效果。同样,将下部分写成具有下拉功能的控件,也根据拉动的距离将上部分在垂直方向上移动。
这种思路需要处理上下拉控件,并且在拉动过程中得设置回调,在回弹过程中一样得设置回调,这样才能达到两者同时滚动的效果。同时,上下部分在垂直方向上的移动需要一个单独的类进行协调。并且根据下部分控件的变化,需要不断地自定义带有下拉功能的控件。
思路二
利用CoordinatorLayout与Behavior,只需要自定义上拉加载下部分的Behavior与下拉加载上部分的Behavior即可。
示例
上拉加载的Behavior。注:上部分使用的是NestedScrollView,support v4中的。它类似于ScrollView,但可以与CoordinatorLayout一起使用。如下:public class FooterBehavior extends CoordinatorLayout.Behavior { private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); public FooterBehavior() { } public FooterBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { return target.getId() == R.id.anchor && isBottom((NestedScrollView) target) && (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0 ; //判断正在垂直滑动的控件是不是自己想要的,并且正处于底部 } private boolean isUploaded = false; @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { if (dy > 0) {//上滑 } else {//下滑 if (sum > 0) {//已经上滑了一部分,此时又进行下滑。因此,需要将此时的下滑给屏蔽掉 isUploaded = true; consumed[1] = dy;//禁止target的自身滑动。此时不会回调onNestedScroll方法,因此需要自己处理垂直位移 sum += dy; ViewCompat.setTranslationY(child, -sum); ViewCompat.setTranslationY(target, -sum); } } } private int sum; @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { if (sum < child.getHeight()) { sum = dyUnconsumed + sum; if (sum > child.getHeight()) sum = child.getHeight(); ViewCompat.setTranslationY(child, -sum); ViewCompat.setTranslationY(target, -sum); } } @Override public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { if (sum < child.getHeight() / 2) {//手指离开时,根据滑动距离判断是回弹还是继续上拉 hide(child); hide(target); } else { show(child, -target.getHeight()); show(target, -target.getHeight()); } if (isUploaded) {//滑动过程中下拉过,因此屏蔽掉下拉时对NestedScrollView造成的fling效果 ((NestedScrollView) target).fling(0); } isUploaded = false; sum = 0; } //判断NestedScrollView是否滑动到底部 private boolean isBottom(NestedScrollView scrollView) { int height = scrollView.getHeight(); int height1 = scrollView.getChildAt(0).getHeight(); return scrollView.getScrollY() >= height1 - height; } //通过属性动画隐藏和显示指定的内容 private void hide(final View view) { ViewPropertyAnimator animator = view.animate().translationY(0).setInterpolator(INTERPOLATOR).setDuration(200); animator.start(); } private void show(final View view, int target) { ViewPropertyAnimator animator = view.animate().translationY(target).setInterpolator(INTERPOLATOR).setDuration(200); animator.start(); }}
以下是下拉时的Behavior,大部分思路与上面的Behavior类似。它的child是RecyclerView。如下:
public class HeaderBehavior extends CoordinatorLayout.Behavior<View> { private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); public HeaderBehavior() { } public HeaderBehavior(Context context, AttributeSet attrs) { super(context, attrs); } private int mInitY; @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { mInitY = (int) ViewCompat.getTranslationY(child); sum = (int) ViewCompat.getTranslationY(child); return target.getId() == R.id.tv && isTop(child, target) && (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; } private boolean isUploaded = false; @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { if (dy > 0) {//上滑 if (sum > mInitY) {//已经下拉出一部分,所以此时上滑不应该再没去target isUploaded = true; consumed[1] = dy;//禁止target的自身滑动。此时不会回调onNestedScroll方法,因此需要自己处理垂直位移 sum -= dy; ViewCompat.setTranslationY(child, sum); ViewCompat.setTranslationY(target, sum); } } else {//下滑 } } private int sum; @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { if (Math.abs(sum) <= child.getHeight()) {//sum < 0 sum -= dyUnconsumed; if (sum >= 0) sum = 0; ViewCompat.setTranslationY(child, sum); ViewCompat.setTranslationY(target, sum); } } @Override public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { if (Math.abs(sum) > target.getHeight() / 2) { show(child, -child.getHeight()); show(target, -child.getHeight()); } else { hide(child); hide(target); } if (isUploaded) { ((RecyclerView) target).stopScroll(); } isUploaded = false; sum = 0; } private boolean isTop(View child, View target) { RecyclerView view = (RecyclerView) target; LinearLayoutManager lm = (LinearLayoutManager) view.getLayoutManager(); return ViewCompat.getTranslationY(target) == -child.getHeight() && lm.findFirstCompletelyVisibleItemPosition() == 0; } private void hide(final View view) { ViewPropertyAnimator animator = view.animate().translationY(0).setInterpolator(INTERPOLATOR).setDuration(200); animator.start(); } private void show(final View view, int target) { ViewPropertyAnimator animator = view.animate().translationY(target).setInterpolator(INTERPOLATOR).setDuration(200); animator.start(); }}使用如下:
<com.example.demo.DemoView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/co" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.NestedScrollView android:id="@+id/anchor" app:layout_behavior="com.example.hufeng.demo.HeaderBehavior" android:layout_width="match_parent" android:layout_height="wrap_content"> <!--保存高度超过屏幕高--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="500dp" android:background="@android:color/holo_red_dark" /> <View android:layout_width="match_parent" android:layout_height="500dp" android:background="@android:color/holo_green_light" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> <android.support.v7.widget.RecyclerView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" android:background="@android:color/holo_red_light" android:textColor="@android:color/white" app:layout_behavior="com.example.hufeng.demo.FooterBehavior" /></com.example.demo.DemoView>
其根结果的DemoView继承于CoordinatoryLayout,只是将其子View按垂直排列,并且可以排到屏幕之外。代码如下:
public class DemoView extends CoordinatorLayout { public DemoView(Context context) { super(context); } public DemoView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec,heightMeasureSpec); int sum = 0; for(int x = 0;x<getChildCount();x++){ sum += getChildAt(x).getMeasuredHeight(); } setMeasuredDimension(getMeasuredWidth(),MeasureSpec.makeMeasureSpec(sum,MeasureSpec.EXACTLY)); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); int top = 0; for (int x = 0; x < getChildCount(); x++) { View view = getChildAt(x); view.layout(l, top, r, top + view.getMeasuredHeight()); top += view.getMeasuredHeight(); } }}
0 0
- Behavior的demo——粗仿天猫详情页效果
- Android——仿美团商品详情页折叠效果
- CoordinatorLayout.Behavior自定义效果的实现
- iOS—UIWindow的详情
- 商品详情的图片放大效果
- 今天实现了类似淘宝上划操作显示详情页的demo
- Android仿最美应用详情页动画效果
- 【技巧】仿某宝网详情页宝贝放大镜效果
- 一个单用户博客系统DEMO——文章详情中插入评论表单
- 商品详情页面demo
- 矫情的C++——不明确行为(undefined behavior)
- 自定义御泥坊(淘宝、360手机卫士)产品详情页的布局悬停效果
- 百度地图SDK for Android【Demo Place详情页】
- 百度地图SDK for Android【Demo Place详情页】
- Android 仿淘宝商品详情页下拉足迹Demo
- 利用ionic里的<ion-slide-box>和 modal 做个仿淘宝商品详情页顶部轮播图的demo
- 商品详情放大效果
- Silverlight behavior 实现水印效果
- 深入了解windows句柄
- HDU 3001 Travelling(状压DP)
- mycat读写分离与主从切换
- 五模十频
- Objextive-C入门学习1--使用NSLog函数在屏幕上打印HelloWorld
- Behavior的demo——粗仿天猫详情页效果
- 普里姆算法、克鲁斯卡尔算法、最短路径
- 每天学习十分钟21之界面原型设计
- Unity问答第4期
- 关于void GetMemory(*p)与void* GetMemory()的讨论
- Android中的异步通信类AsyncTast
- java 的文件操作
- 移动定位业务之“A-GPS(辅助全球卫星定位系统)”
- 论“神”