Material Design中的一些趣事
序言:前两天接到一个任务,说是要实现一个类似下面这样的界面:
当然了,这个是我完成任务之后又写的一个demo,大家可能会想到这里用的是谷歌极力推荐我们使用的一个全新的设计语言——Material Design,然后再配上谷歌的下拉刷新控件SwipeRefreshLayout,没错,这里我们就是这样干的,因为只有一个刷新,却有三个页面,所以这里还有一个需要注意的地方就是刷新之后三个页面的数据分配问题,待会我们再来讲这个问题。
首先我们来看布局,最上面是我们自己的一个标题栏,往下图片那一整块我用的是toolbar,里面包含了整个的头部信息,再往下面是一个Tablayout,里面是三个tab,最下面放的是三个fragment
好了,我们来看看布局信息
<android.support.v4.widget.SwipeRefreshLayout>
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout>
<android.support.v7.widget.Toolbar>
整个头部(标题栏以下)
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<LinearLayout>
<android.support.design.widget.TabLayout>
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager>
</android.support.v4.view.ViewPager>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
</android.support.v4.widget.SwipeRefreshLayout>
看起来挺蛮烦的哈,但是为了要达到上面那种效果,也是没啥办法了。布局写完之后,我们来完成viewpager和Fragment的结合。我们的ViewPager需要一个FragmentPagerAdapter来填充,在adapter中我们需要注意的是Fragment一定要写成员变量,切记不可在getItem方法中返回的时候直接new一个Fragment对象,这样你会后悔的,因为下文我们要讲到刷新之后数据分配的问题,下面我们再说。
@Override
public Fragment getItem(int position) {
if (position == 1) {
if (fragmentTwo == null) {
fragmentTwo = new FragmentTwo();
}
return fragmentTwo;
} else if (position == 2) {
if (fragmentThree == null) {
fragmentThree = new FragmentThree();
}
return fragmentThree;
} else {
if (fragmentOne == null) {
fragmentOne = new FragmentOne();
}
return fragmentOne;
}
}
然后呢,我们就要实现刷新的功能了,刷新的时候我们还需要注意一点,就是当你把toolbar里面的内容(也就是整个头部)顶上去之后,再下拉,它会立马进行刷新,不会等到你把toolbar中的内容拉到正常状态再进行刷新,详细解决方案请参考
CoordinatorLayout AppBarLayout 结合下拉刷新 上拉加载更多 的滑动冲突解决
也就是说我们需要监听appbarlayout的滚动
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
if (verticalOffset >= 0) {
swipeRefreshLayout.setEnabled(true);
} else {
swipeRefreshLayout.setEnabled(false);
}
}
});
这样我们就不用担心还没有将toolbar的内容全都拉下来就执行刷新了,这里效果图我们就不放了,有兴趣的哥们可以自己尝试一把。接下来我们来看刷新之后数据分配的地方,这里我们使用set方式直接将数据设置到Fragment中的方法中,然后再由Fragment中的方法进行数据的展示。
首先,在Activity中,我们可以根据ViewPager.getCurrentItem()方法来判断我们处于哪个fragment中,然后我们在Fragment中写set方法:
public void setDatas(List<String> datas) {
mDatas.addAll(0, datas);
mAdapter.notifyDataSetChanged();
}
这样方便在Activity中调用。这里可能就有人要问了,我拿到了数据,知道了是哪一个fragment,但是我怎么获取fragment对象呢?别急,我们还有一个FragmentPagerAdapter嘛!根据adapter.getItem(position)我们就可以获取fragment,注意注意注意,重要的事情说三遍,上面我们说到不能在adapter中的getItem方法中返回的时候直接new一个对象,因为我们每次在Activity中调用adapter.getItem的时候adapter都会创建一个新的Fragament对象,然后你之前初始化过的一些东西就会没了,然后当你设置数据的时候就回空指针了
来看一下我们如何调用set方法:
((Fragment) FragmentPagerAdapter.getItem(position)).setDatas(datas);
这一篇主要讲的是在做这个效果的时候所需要注意的地方,怎么做的在这里就不细讲了,往上的demo有很多,大家可以百度试着写写看,遇到什么问题再来看看这篇文章。
这里有其它的读者使用这个的时候遇到一个问题,就是如果fragment中不是列表,是普通的一个布局,或者一个webview,滑动的时候会有冲突的,具体什么样子的感兴趣的朋友可以去试试,这里我们直接给出解决方案:
在布局的最晚层嵌套一个NestedScrollView就可以了,如果还有其他的问题,也欢迎加群跟我一起交流!!!