CoordinatorLayout + AppBarLayout + SwipeRefreshLayout在eclipse上使用的方法和问题记录

来源:互联网 发布:mac word选项 编辑:程序博客网 时间:2024/06/06 17:13


项目开始使用的eclipse进行开发。


需求


在做一个界面时

状态栏下面是标题栏,黄色的图片是头部的viewpager,再下面是fragment的名字的tab,tab下面是viewpager,viewpager中是fragment,

要求是上拉时整体上滑,tab栏到顶部时停留列表继续上滑, 下拉时列表下滑显示完全以后,再下拉头部视图,这个界面结构并不难做,我开始用的一个自定义组件,以前做demo时使用过,

就是这两个,单独使用并没有问题,但是我的3个fragment都有刷新需求,所以我想把SwipeRefreshLayout套在整个布局的外面,然后通过接口将刷新事件传递到fragment中去,问题出现了,下拉上拉各种冲突,鉴于重点不是这个就不描述了,类似的冲突后面也会出现,再说解决方法。重点是CoordinatorLayout + AppBarLayout在eclipse中的使用,和嵌套刷新冲突的解决。


在eclipse中使用:


开始说了项目用的eclipse,所以并不能像网上一片片的compile来使用design库,我就从sdk中复制了design库出来,当做library引入项目中,然后使用:

有flag,有behavior,有正确的嵌套,但是fragment中的recyclerview上滑时,标记了flag的view并没有上滑隐藏,单独滑动这个view是可以的,始终确定不了原因,然后就想着是版本问题吗,因为我使用的是recyclerview是以前项目用的jar,可能比较老呢? 于是复制了sdk中的recyclerview出来当库引入,好了... ,现在的布局是CoordinatorLayout + AppBarLayout,实现了和自定义布局ScrollableLayout相似的功能,然后加上SwipeRefreshLayout,又出现了滑动冲突的问题,使用ScrollableLayout时这个问题解决过,但是可能因为自定义view本身逻辑不严密吧,偶尔还是有bug,所以才使用design库,也正好学习下里面的组件,出现这个冲突时,百度了下,AppBarLayout 自带了一个监听器OnOffsetChangedListener ,用来告诉你他的偏移量,只要计算这个偏移量然后设置swiperefreshlayout的enable属性,让刷新组件在appbarlayout没有滑下来时不活动就能解决。


实际使用中的问题:


但是实际使用时并没有这么简单。fragment切换时的状态变化,recyclerview的item上间距等等都会影响,举个例子吧,fragment 1 的recyclerview上拉,appbarlayout中的带flag的view隐藏了,swipe的enable=false, 然后切换到fragment 2 , 2中的recyclerview下拉,吧appbarlayout中的view拉下来,这时OnOffsetChangedListener 监听器的偏移量是0,swipe的enable属性=true,表示是可以刷新的,然后又切换到fragment 1, 1中的recyclerview并没有在顶部,应该是不能刷新的,但是swipe的enable是true,所以他刷新了,类似的冲突还有其他情况,我直接说解决的办法吧。


解决过程:


使用了两个监听器,一个是自定义的监听AppBarLayout偏移量的OnOffsetChangedListener,另一个是fragment切换时获取其中的recyclerview对象的监听器OnCurrentRvListener,


AppBarOffsetChangedListener 综合判断偏移量,recyclerview是否滑动到顶部,来设置是否允许刷新,

RvTop.isRecyclerViewTop(listener.getRv(),listener.getTopSpec()) 这个方法就是判断recyclerview是否滑动到顶部了,


OnCurrentRvListener 监听室由viewpager中的fragment实现,返回fragment中的recyclerview对象和recyclerview的item上间距。


AppBarLayout便宜量的监听器AppBarOffsetChangedListener初始化时传入了swipeRefreshLayout的对象,但是他持有的OnCurrentRvListener 的对象在fragment切换时是会改变的,所以使用时应该动态设置AppBarOffsetChangedListener中的OnCurrentRvListener 的对象。


setCurrent()就是fragment切换的方法,OnCurrentRvListener 是由fragment实现的,所以OnCurrentRvListener 对象的初始化是在setCurrent()方法中,



当fragment切换时,重新获取OnCurrentRvListener 对象并设置到AppBarOffsetChangedListener中去,这样AppBarLayout监听器偏移量变化时拿到的才是当前fragment中的recyclerview对象;


加上这两个监听器以后解决了一部分冲突,但并没有完全解决。这个最终还是依靠AppBarLayout的偏移量监听器来设置是否允许刷新的,但是这个监听器有时并不会触发,所以有时还需要主动去触发监听器,上图,在setCurrent()方法中切换fragment时主动触发一下,调用了setSrlState()方法

public void setSrlState(){

if(offsetListener != null){

offsetListener.onOffsetChanged(mAppBarLayout, mAppBarLayout.getTop());
}

}

再在recyclerview的OnScrollListener中设置,

if (llManager.findFirstVisibleItemPosition() == 0) {
mRecordFragment.setSrlState();
}

当显示第一个item时又主动去调用。

到这就差不多解决了我用了一段时间没发现有冲突了,是过了一段时间才写的,所以哪里有遗漏以后再补吧,


其他情况


CoordinatorLayout + AppBarLayout的简单使用网上一大把就不粘了,

另外做这块的时候发现水平滑动本来是触发viewpager左右滑动的,但是偏了一点就会触发刷新,所以自定义了viewpager 来解决这个滑动冲突,附上代码,思路就是 通过setSrl()方法把SwipeRefhreshlayout对象传到viewpager中,然后在dispatchTouchEvent事件中获取手指按下的坐标,在onTouchEvent的move事件中判断手指滑动的角度,设置是否允许刷新。在up和cancel中还原swiperefreshLayout对象的状态。











0 0
原创粉丝点击