下面的recyclerview支持下拉刷新和加载更多,同时支持Tablayout滑动悬浮置顶,同时为了解决列表下拉刷新和AppBarLayout滚动视图滑动冲突,
发现有两种方案:
1,列表直接不支持下拉刷新,只支持加载更多
2,列表支持下拉刷新,但是需设置当AppBarLayout完全收缩时开启,在AppBarLayout展开时不能下拉刷新。
1,布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tl="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="txkj.xian.com.txproject.activity.TestIndexActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/gray"
android:orientation="horizontal">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="标题栏搜索"
android:textAlignment="center"
android:textColor="@color/black_6"
android:textSize="18sp" />
</LinearLayout>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
app:layout_behavior="@string/no_scroll_behavior">
<android.support.constraint.ConstraintLayout
android:id="@+id/const_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll">
<com.youth.banner.Banner
android:id="@+id/banner"
android:layout_width="0dp"
android:layout_height="0dp"
app:banner_default_image="@drawable/default_image"
app:indicator_drawable_selected="@drawable/banner_indicator_select_color"
app:indicator_drawable_unselected="@drawable/banner_indicator_unselect_color"
app:indicator_height="5dp"
app:indicator_margin="2dp"
app:indicator_width="5dp"
app:layout_constraintDimensionRatio="h,720:326"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:title_textcolor="@color/white"
app:title_textsize="15sp" />
</android.support.constraint.ConstraintLayout>
<com.flyco.tablayout.SlidingTabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@color/white"
tl:tl_indicator_color="@color/newtitle"
tl:tl_indicator_height="2dp"
tl:tl_indicator_style="NORMAL"
tl:tl_tab_space_equal="true"
tl:tl_textSelectColor="@color/newtitle"
tl:tl_textUnselectColor="@color/black_2"
tl:tl_textsize="14sp" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
2,AppBarLayout使用了自定义的behavior,用于控制appbar的滑动,代码如下:
public class NoScrollBehavior extends AppBarLayout.Behavior{
public boolean noScroll;
public NoScrollBehavior() {
}
public NoScrollBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean isNoScroll() {
return noScroll;
}
public void setNoScroll(boolean noScroll) {
this.noScroll = noScroll;
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
if (noScroll) {
return false;
} else {
return super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
}
}
}
3,Activity中代码如下:
public class TestIndexActivity extends BaseActivity implements AppBarLayout.OnOffsetChangedListener {
@BindView(R.id.banner)
Banner banner;
@BindView(R.id.tabLayout)
SlidingTabLayout tabLayout;
@BindView(R.id.viewpager)
ViewPager viewPager;
@BindView(R.id.appBarLayout)
AppBarLayout appBarLayout;
@BindView(R.id.textView)
TextView textView;
private boolean isAlreadyInit;
private List<BaseLazyLoadFragment> mFagments = new ArrayList<>();
private String[] mTitles = new String[]{"推荐","精选"};
private NoScrollBehavior myAppBarLayoutBehavoir; // 自定义的 behavior 用于控制appbar的滑动
private ZixunFragment2 currentFragment;
@Override
public int setLayout() {
return R.layout.activity_test_index;
}
@Override
public void initView() {
myAppBarLayoutBehavoir = (NoScrollBehavior)
((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
// 获取顶部banner数据
getBannerData();
mFagments.add(ZixunFragment2.getInstance("1"));
mFagments.add(ZixunFragment2.getInstance("2"));
MyAdapter adapter = new MyAdapter(getSupportFragmentManager(), mFagments);
viewPager.setAdapter(adapter);
// 设置标题选项
tabLayout.setViewPager(viewPager, mTitles);
currentFragment = (ZixunFragment2) mFagments.get(0);
}
@Override
protected void setListener() {
appBarLayout.addOnOffsetChangedListener(this);
tabLayout.setOnTabSelectListener(new OnTabSelectListener() {
@Override
public void onTabSelect(int position) {
currentFragment = (ZixunFragment2) mFagments.get(position);
}
@Override
public void onTabReselect(int position) {
}
});
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
currentFragment = (ZixunFragment2) mFagments.get(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//返回监听 当appBar处于不可滑动(即完全折叠)时,先释放appBar
if (myAppBarLayoutBehavoir.isNoScroll()) {
myAppBarLayoutBehavoir.setNoScroll(false);
// 设置appbar展开
appBarLayout.setExpanded(true, true);
} else {
// mSwipeBackHelper.backward();
}
}
});
}
@Override
public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
//顶部渐变 标题栏处理 滑动竖直距离/appBarLayout滚动区域的总高度 值变化范围:0~1
float percent = Float.valueOf(Math.abs(verticalOffset)) / Float.valueOf(appBarLayout.getTotalScrollRange());
// 滑动事件处理
if (percent == 0) {
// 为0代表没有滑动,即完全展开时 appbar可滑动 禁止refresh(可根据需求不禁止刷新)
myAppBarLayoutBehavoir.setNoScroll(false);
currentFragment.setRefreshState(false);
} else if (percent == 1) {
//为1代表完全折叠 appbar不可滑动使tab吸顶 允许refresh
currentFragment.setRefreshState(true);
myAppBarLayoutBehavoir.setNoScroll(true);
} else {
// 滑动中,介于0和1之间 appbar可滑动 禁止refresh(建议禁止刷新,否则会appbar影响滑动流畅)
myAppBarLayoutBehavoir.setNoScroll(false);
currentFragment.setRefreshState(false);
}
}
public class MyAdapter extends FragmentPagerAdapter {
private final List<BaseLazyLoadFragment> mFagments;
public MyAdapter(FragmentManager fm, List<BaseLazyLoadFragment> mFagments) {
super(fm);
this.mFagments = mFagments;
}
@Override
public Fragment getItem(int position) {
return mFagments.get(position);
}
@Override
public int getCount() {
return mFagments.size();
}
}
// 参数表示是不是更新
private void getBannerData() {
OkGo.<HomeBanner>>get(UrlConstant.GET_BANNER)
.tag(this)
.execute(new JsonCallback<ResponseResult<HomeBanner>>() {
@Override
public void onSuccess(Response<ResponseResult<HomeBanner>> response) {
ResponseResult<HomeBanner> body = response.body();
int code = body.getCode();
if (code == 200) {
if(!isAlreadyInit){
List<String> images = new ArrayList<>();
List<HomeBanner.BannerBean> banner2 = body.getData().getBanner();
for (HomeBanner.BannerBean hb : banner2) {
images.add(hb.getImgUrl());
}
initBanner(images);
isAlreadyInit = true;
}
} else {
// banner数据获取失败
}
}
});
}
// 顶部Banner轮播
private void initBanner(List<String> images) {
if (banner != null) {
//设置banner样式
banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR);
//设置图片加载器
banner.setImageLoader(new GlideImageLoader());
//设置图片集合
banner.setImages(images);
//设置banner动画效果
banner.setBannerAnimation(Transformer.Default);
//设置标题集合(当banner样式有显示title时)
// banner.setBannerTitles(titles);
//设置自动轮播,默认为true
banner.isAutoPlay(true);
//设置轮播时间
banner.setDelayTime(5000);
//设置指示器位置(当banner模式中有指示器时)
banner.setIndicatorGravity(BannerConfig.CENTER);
//banner设置方法全部调用完毕时最后调用
banner.setOnBannerListener(new OnBannerListener() {
@Override
public void OnBannerClick(int position) {
Toast.makeText(TestIndexActivity.this, "点击"+position, Toast.LENGTH_SHORT).show();
}
});
banner.start();
}
}
@Override
public void onDestroy() {
super.onDestroy();
appBarLayout.removeOnOffsetChangedListener(this); // 解除监听
}
}
其余的就是定义fragment,实现不同的列表,需要注意的是在fragment中需要提供一个可以设置开启和关闭下拉刷新的方法,如下:
public void setRefreshState(boolean b) {
refreshLayout.setEnabled(b);
}
以上主要使用到的第三方开源库包括:
1,Banner轮播图:com.youth.banner:banner:1.4.10
2,TabLayout选项切换:FlycoTabLayout_Lib
3,下拉刷新:SmartRefreshLayout
4,RecycleView:BaseRecyclerViewAdapterHelper
5,不同状态(无网络,无数据等)视图切换库:com.ganxin.library:loaddatalayout:1.0.1