Android自定义控件——FloatLayout

本文详细介绍了如何实现类似美团、微博等应用中的浮动物件布局,名为FloatLayout。该布局由HeaderLayout、FloatLayout和ContentLayout三部分组成,通过ViewPager+Fragment实现内容展示。关键在于计算ContentLayout的高度并处理滑动事件分发,以实现HeaderLayout完全隐藏时,FloatLayout悬浮在顶部的效果。同时提供了GitHub上的源码链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文介绍一个好多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) f