先看下效果:
这种布局吸附效果在实际开发中很常见,也是比较合适的需求,如何来实现这个效果我们就要分析一下。
1.如图上所示,我们添加两个吸附布局,a,b其实这个两个布局是一样的
2.最外层view是 Scrollview。
3.最开始的时候让 吸附布局a,b重合绘制,当吸附布局a滚动上面的时候,吸附布局b不断根据绘制,一直停留在顶部。
看下具体代码吧:
主要布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:background="@color/colorAccent"
android:layout_height="?actionBarSize">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="商品详情"
android:textSize="22dp"
android:layout_centerInParent="true"
android:textColor="@android:color/white"/>
</RelativeLayout>
</android.support.v7.widget.Toolbar>
<com.test.scrolltransptoolbar.GradationScrollView
android:id="@+id/scrollview"
android:layout_height="match_parent"
android:layout_width="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:src="@mipmap/tup"/>
<include android:id="@+id/top_rl" layout="@layout/buy"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textSize="18dp"
android:text="转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17761431),请尊重他人的辛勤劳动成果,谢谢!
我之前写了一篇关于美团网,大众点评的购买框效果的文章Android对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果,我自己感觉效果并不是很好,如果快速滑动界面,显示悬浮框的时候会出现一卡的现象,有些朋友说有时候会出现两个布局的情况,特别是对ScrollView滚动的Y值得监听,我还使用了Handler来获取,还有朋友给我介绍了Scrolling Tricks这个东西,我下载试了下,确实美团网,大众点评的购买框用的是这种效果,但是Scrolling Tricks只能在API11以上使用,这个有点小悲剧,然后我做了下修改,并将实现思路分享给大家,实现起来很简单
首先还是要先对ScrollView进行滚动监听,直接在onScrollChanged()方法中当myScrollView向上滚动,而上面购买布局的上边缘始终要和myScrollView的上边缘保持mBuyLayout.getTop()这个距离,所以上面的购买布局也跟着向上滚动,当scrollY大于mBuyLayout.getTop()的时候,表示购买布局上边缘滑动到了导航栏布局,所以此时购买布局的上边缘与myScrollView的上边缘始终要保持scrollY这个距离,所以购买布局才会一直在导航栏下面,就好像粘住了一样,不知道你了解了没有?好了,不过根据这种思路你也可以刚开始使用一个悬浮框来覆盖在下面的购买布局上面,然后onScroll()方法中更新悬浮框的位置,不过悬浮框的x,y不是相对于就能获取滚动的Y值,之前那篇文章使用了Handler,走弯路了,直接看代码吧"/>
</LinearLayout>
<include android:id="@+id/top_rl1" layout="@layout/buy"/>
</FrameLayout>
</com.test.scrolltransptoolbar.GradationScrollView>
</LinearLayout>
layout=”@layout/buy” 代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="5dp"
android:paddingLeft="10dp"
android:background="@android:color/white"
android:paddingRight="10dp">
<TextView
android:id="@+id/jia_ge_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="¥ 17.8"
android:textColor="#F3C80A"
android:textSize="20dp"
android:textStyle="bold" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/jia_ge_tv"
android:layout_marginTop="5dp">
<TextView
android:id="@+id/hua_jia_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="价格 ¥20元" />
<View
android:layout_width="wrap_content"
android:layout_height="0.5dp"
android:layout_alignLeft="@id/hua_jia_tv"
android:layout_alignRight="@id/hua_jia_tv"
android:layout_centerInParent="true"
android:background="@android:color/darker_gray" />
</RelativeLayout>
<Button
android:layout_width="100dp"
android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="#F89909"
android:text="立即抢购"
android:textColor="@android:color/white"
android:textSize="16dp" />
</RelativeLayout>
Activity代码:
package com.test.scrolltransptoolbar;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
/**
* Created by Administrator on 2017/8/29.
*/
public class SuspensionEffectActivity extends Activity implements GradationScrollView.ScrollViewListener {
private GradationScrollView scrollview;
private RelativeLayout top_rl;
private RelativeLayout top_rl1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_suspension_effect);
findViewById();
}
private void findViewById() {
scrollview = (GradationScrollView) findViewById(R.id.scrollview);
top_rl = (RelativeLayout) findViewById(R.id.top_rl);
top_rl1 = (RelativeLayout) findViewById(R.id.top_rl1);
scrollview.setScrollViewListener(this);
top_rl.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Log.i("onGlobalLayout","onGlobalLayout++");
onScrollChanged(null,0,scrollview.getScrollY(),0,0);
top_rl.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
}
@Override
public void onScrollChanged(GradationScrollView scrollView, int x, int y, int oldx, int oldy) {
int mBuyLayout2ParentTop = Math.max(y, top_rl.getTop());
top_rl1.layout(0,mBuyLayout2ParentTop,top_rl1.getWidth(),mBuyLayout2ParentTop+top_rl1.getHeight());
}
}
这段代码的作用就是让最开始的时候吸附布局b与吸附布局a位置重叠
top_rl.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Log.i("onGlobalLayout","onGlobalLayout++");
onScrollChanged(null,0,scrollview.getScrollY(),0,0);
top_rl.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
int mBuyLayout2ParentTop = Math.max(y, top_rl.getTop()); 比较两个数值谁的大
往上滚动,滚动y的值会越来越大,top_rl1.layout()就会绘制在顶部,如果小于的话位置就会跟吸附布局a重合
@Override
public void onScrollChanged(GradationScrollView scrollView, int x, int y, int oldx, int oldy) {
int mBuyLayout2ParentTop = Math.max(y, top_rl.getTop());
top_rl1.layout(0,mBuyLayout2ParentTop,top_rl1.getWidth(),mBuyLayout2ParentTop+top_rl1.getHeight());
}
package com.test.scrolltransptoolbar;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;
/**
* 带滚动监听的scrollview
*
*/
public class GradationScrollView extends ScrollView {
public interface ScrollViewListener {
void onScrollChanged(GradationScrollView scrollView, int x, int y,
int oldx, int oldy);
}
private ScrollViewListener scrollViewListener = null;
public GradationScrollView(Context context) {
super(context);
}
public GradationScrollView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
public GradationScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
}
}
}
onScrollChanged,这个方法是ScrollView 私有的所以需要重写暴露出来
参考大神:
http://blog.csdn.net/xiaanming/article/details/17761431
这种效果叫:ScrollingTricks