其实这个标题并不能完整表达实际的效果的描述,因为在开发很多应用的过程中,我们都有这么一个需求,那就是在某个页面中,又一行(或者一列)作为导航的菜单,而整页的内容,又因为过长而不得不加入滚动试图,如果说只是这样简单的需求的话,我们直接把导航的菜单固定在边缘,那样就一劳永逸了,但是实际上很多需求并不是简单的这样处理的,比如:在一个页面的顶部是缩略图,接着中间是一栏导航,下面是具体的内容;如图:
如果我们把顶部的图片和导航固定,那么下部可动范围就太小了,所以,更多的时候我们是需要这样的处理,当开始拖动界面以查看底部更多内容的时候,让界面中顶部的图片和中部的导航一起动,但是当导航栏到达顶部的时候,便固定在那里;同时,当拖动界面往下,底部内容拉去完以后,应该是导航栏和顶部图片一起往下,拖动到最后恢复为初始的样子。
根据现有的需要,我的简单思路是这样处理,整个页面是放入一个ScrollView之中,再加入一个默认是View.GONE的FrameLayout中,布局一个和在ScrollView中的导航栏一样的导航栏;监听ScrollView的滑动事件,当ScrollView的导航栏view的getLocationInWindow()获得的坐标y <= ScrollView.y,则处理把FrameLayout的导航栏显示出来,同理,返回时逆向处理。
思路基本理清,现在要做的就是实际的监听如何完成,因为ScrollView不是ListView可以监听滚动,默认的ScrollView只有一个onTouch(),虽然这个看似也能解决我们的问题,但是实际上,当你快速滑动的时候,你就会发现,想要的置顶的导航栏没有显示出来,直到再次触到屏幕,在能出来,显然这样的效果是不如意的。
纠结过后,考虑可否使用一个线程,每隔200ms触发一次判断,如果应该显示置顶的导航栏了,发送一个消息,然后处理,我测试了一下代码,这样的方法固然可行,但是后来想想,这样的操作,似乎不是很好,最后还是从测试代码中删去,不过这个方法可以作为备选方案。
经过几番摸索,觉得修改ScrollView来实现类似ListView的滚动监听似乎比较靠谱,所以决定写一个ObservableScrollView,这个类是继承ScrollView的,在内部增加一个借口回调,代码如下:
1 | package com.ilovn.app.test.floatnav; |
这个ObservableScrollView是比较通用的,实际上我们这里的效果不需要那么详细的参数,只需要在scroll的视图实现这个借口,在回调函数中,处理导航栏的显示与消失即可。
看一下效果图:
本文系原创,转载请注明出处!