谷歌新出的Android Design Support Library带来了新的兼容的md风格控件,其中的coordinatorlayout配合appbarlayout再指定behavior可以实现滚动的效果,然而很遗憾,在应用到项目的时候,出现各种问题,比如:
1.我所在的coordinatorlayout布局里需要用到viewstub作为网络请求异常时懒加载的布局,在coordinatorlayout如果延时20多ms再去viewstub.inflate的话布局就找不到了,在relativelayout这些布局就是可以随时调用加载显示。
2.首先向上滚动recycleview,直到tablayout跟随滚动被隐藏,切换到其他fragment再切换回coordinatorlayout所在的fragment,向下滚动recycleview回到位置0的话,tablayout不会滚回来了,需要稍微先上滑动一下再向下话才能回来,估计是tablayout设置的属性app:layout_scrollFlags=”scroll|enterAlways”问题。
3.向上滚动recycleview到一定位置,点击回到顶部的按钮,调用scrollToPosition(0)回到位置0的话,tablayout也是不会滚回来的,也是需要稍微先上滑动一下再向下话才能回来。
所以思考调试了很久还是决定自己动手,丰衣足食,不要coordinatorlayout,再tablayout的包裹布局,通过监听recycleview的onscroll事件,取每次偏移量,调用tablayout的包裹布局的scrollby(0,dy)来实现移动,并针对快速滑动时偏移量的突增进行了判断和处理,最终实现了较好的tablayout随recycleview滚动而滚动效果,这样用户滑动recycleview时能够看到更多的内容,体验又提升了。
首先看下mainactivity的布局:
viewpager和tablayout放在帧布局里面,这样做是为了,recycleview位置0的地方添加一个跟tablayout等高的view,从而tablayout不会遮住recycleview的图片item
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/material_primary"
app:popupTheme="@style/Theme.AppCompat.Light">
android.support.v7.widget.Toolbar>
<FrameLayout
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/material_primary"
app:tabGravity="center"
app:tabIndicatorColor="@color/material_white_500"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/material_white_500"
app:tabTextColor="@color/material_grey_300" />
RelativeLayout>
FrameLayout>
RelativeLayout>
然后看下mainactivity关键代码:
toolbar设置这里添加一个单击回到recycleview顶部的textview
private void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setTitle("");
TextView tv = new TextView(this);
tv.setText("点击跳回顶部");
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// EventBus通知此tag对于订阅事件者返回顶部
EventBus.getDefault().post(new EventBusElement(), "scrollToTop");
}
});
// toolbar添加一个可点击返回顶部的textview
mToolbar.addView(tv);
setSupportActionBar(mToolbar);
}
设置测试的标签给tablayout和创建fragment到viewpager中
private void initData() {
ArrayList tabTitles = new ArrayList<>();
tabTitles.add("AAAA");
tabTitles.add("BBBB");
tabTitles.add("CCCC");
tabTitles.add("DDDD");
tabTitles.add("EEEE");
tabTitles.add("FFFF");
tabTitles.add("GGGG");
tabTitles.add("HHHH");
List fragments = new ArrayList<>();
for (int i = 0; i < tabTitles.size(); i++) {
// tablayout添加标签
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitles.get(i)));
fragments.add(new HomeSimpleFragment());
}
FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(), fragments, tabTitles);
mViewPager.setAdapter(adapter);
mTabLayout.setupWithViewPager(mViewPager);
mTabLayout.setTabsFromPagerAdapter(adapter);
}
fragment和mainactivity的交互我选择使用MR.SIMPLE的evenbus来进行,十分便捷,mainactivity这里订阅一个scroollTabLayout的事件,
recycleview在滚动的时候会在onscroll方法发送滚动的偏移量到这个方法,我们拿到偏移量调用mAppBarLayout.scrollBy来移动tablayout,
if (mAppBarLayout.getScrollY() < 0)和if (element.getAppBarOffset() == 12345 && mAppBarLayout.getScrollY() >= 0 && mAppBarLayout.getScrollY() != mTabLayoutHeight)是针对快速滚动后有时会不在正确的位置,这时就需要我们人为判断偏差再移动调整
@Subscriber(tag = "scroollTabLayout")
private void scroollTabLayout(EventBusElement element) {
if (element.getAppBarOffset() != 12345) {
mAppBarLayout.scrollBy(0, element.getAppBarOffset());
}
if (mAppBarLayout.getScrollY() < 0) {
mAppBarLayout.scrollBy(0, -mAppBarLayout.getScrollY());
}
// 位置不为0的情况是快速滑动的时候,传递12345作为快速向下滚动的标志,mainactivity的scroollTabLayout会针对此情况做特殊处理
if (element.getAppBarOffset() == 12345 && mAppBarLayout.getScrollY() >= 0 && mAppBarLayout.getScrollY() != mTabLayoutHeight) {
mAppBarLayout.scrollBy(0, mTabLayoutHeight - mAppBarLayout.getScrollY());
}
}
再来看下HomeSimpleFragment的关键代码:
HomeSimpleFragment也订阅了一个返回到顶部的世界,当mainactivity的toolbar上的text被点击的时候发送通知调用这个方法,
element.setAppBarOffset(-MainActivity.mTabLayoutHeight);
EventBus.getDefault().post(element, “scroollTabLayout”);
是为了返回顶部的时候将tablayout滚动回原来的位置
/**
* 订阅一个返回顶部的事件
*
* @param element
*/
@Subscriber(tag = "scrollToTop")
private void scrollTotop(EventBusElement element) {
mRecyclerView.smoothScrollToPosition(0);
element.setAppBarOffset(-MainActivity.mTabLayoutHeight);
EventBus.getDefault().post(element, "scroollTabLayout");
}
mRecyclerView会设置一个滚动监听,将偏移量传回给mainactivity控制tablayout的滚动
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (mManager.findFirstVisibleItemPosition() == 0) {
// 位置为0的时候传递偏移量给mainactivity的scroollTabLayout处理tablayout的滚动
element.setAppBarOffset(dy);
EventBus.getDefault().post(element, "scroollTabLayout");
} else {
// 位置不为0的情况是快速滑动的时候,传递12345作为快速向下滚动的标志,mainactivity的scroollTabLayout会针对此情况做特殊处理
element.setAppBarOffset(12345);
EventBus.getDefault().post(element, "scroollTabLayout");
}
}
});
PS:mainactivity在viewpager切换的时候
在onPageSelected这里控制tablayout滚回原位,这样是为了提高用户体验,参考的是wish切换时的做法
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
// 页面切换的话,tablayout回到原位
mAppBarLayout.scrollBy(0, -mAppBarLayout.getScrollY());
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
至此,大功告成了!下面看动图的效果吧!
demo地址:
http://download.csdn.net/detail/oushangfeng123/8971049