本文介绍一个好多App都有的布局容器,如图
这种效果在微博,美团,点评上面都有使用,是一种很不错的交互方式。
实现原理:
自定义一个Layout,可以是LinearLayout,RelativeLayout
容器总共有三个部分,HearderLayout最上面的部分,FloatLayout滑动的时候浮动的部分,ContentLayout下面的内容部分,这里我们使用了一个ViewPager+Fragment来代替,以保证满足使用时候的更多可能性。
在初始化容器的时候给容器测算大小,关键是在ContentLayout的大小,ContentLayout的高度是父容器的高度减去FloatLayout的高度,也就是向上滑动的时候当HeaderLayout完全滑出父控件之后,此时的Contentayout的高度加上FloatLayout的高度正好等于父容器的高度
在滑动的时候做事件分发和拦截,主要是处理什么时候滑动内部的ListView或者ScrollView,又在什么时候滑动整个容器。
当HeaderLayout没有完全隐藏的时候就滑动整个容器,当HeaderLayout隐藏的时候滑动内部的ListView或者ScrollView,
当向上滚动的时候,HeaderLayout完全隐藏时,整个容器就不再滚动了,接下来滚动的是ContentLayout的内容,所以就造成了FloatLayout悬浮在顶部的效果。
滚动重写了父容器的scrollTo来保证容器滚动的范围,滚动的范围在整个容器减掉HeaderLayout的高度的范围之内,不能太上,也不能太下。
FloatLayout.java
/**
* 自定义的有悬浮layout的容器,类似微博,美团,点评的效果
*
* @author mingwei
*
*/
public class FloatLayout extends LinearLayout {
private RelativeLayout mHeaderLayout;
private LinearLayout mFloatLayout;
private ViewPager mContent;
private int mHeaderHeight;
private boolean isHeaderHidden;
private ViewGroup mInnerScrollview;
private OverScroller mScroller;
private VelocityTracker mVelocityTracker;
private int mTouchSlop;
private int mMaximumVelocity, mMinimumVelocity;
private float mLastY;
private boolean isDragging;
private boolean isMove = false;
public FloatLayout(Context context) {
this(context, null);
}
public FloatLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FloatLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScroller = new OverScroller(context);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMaximumVelocity = ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
mMinimumVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mHeaderLayout = (RelativeLayout) findViewById(R.id.float_layout_top);
mFloatLayout = (LinearLayout) findViewById(R.id.float_layout_float);
mContent = (ViewPager) findViewById(R.id.float_layout_content);
}
@Override
protected void onMeasure(int widthMeasureSpec,