本Demo链接:http://download.csdn.net/download/g_ying_jie/10123364
先谈下我遇到的需求;fragment中装载viewpager、title标题栏、滑动导航栏,以及DrawerLayout;现在需要各自的滑动互不干扰,上滑隐藏title下滑呼出title。
一、fragment页面的xml布局
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#30469b"
android:gravity="center"
android:text="书刊"
android:textColor="#ffffff"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#30469b"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabSelectedTextColor="#ff0000"
app:tabTextColor="#ffffff" />
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="heheh"/>
</android.support.v4.widget.DrawerLayout>
@注意很多案例的演示,标题栏都是使用的toolbar,但是不要被误导了,上滑隐藏不是toolbar实现的。是靠CoordinatorLayout监控子View的滑动通知给需要隐藏或显示的view,因此对应的behavior标注很重要不可出错
二、另一种更为复杂的布局,仿微云的效果,第一层是tablayout滑动导航,其中文档fragment包含一个搜索框和一个RadioGroup的点击导航。上滑隐藏搜索框,左右滑动切换tablayout,点击响应RadioGroup导航。这里还会出现tablayout来回滑动导致RadioGroup的子Fragment重复添加应用崩溃的问题,后面会谈到解决方法。
文档fragment页面的布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="18dp"
android:orientation="horizontal"
app:layout_scrollFlags="scroll|enterAlways">
<EditText
android:id="@+id/et"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@drawable/bg_search"
android:drawableLeft="@mipmap/search"
android:drawablePadding="8dp"
android:hint="请输入查询名称"
android:imeOptions="actionSearch"
android:inputType="text"
android:padding="6dp"
android:singleLine="true"
android:textColorHint="@color/text_grey" />
<ImageView
android:id="@+id/img_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"
android:src="@mipmap/icon_sort" />
</LinearLayout>
<RadioGroup
android:id="@+id/rg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:background="@drawable/bg_recode_circle"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_all"
style="@style/RadioButtonStyle"
android:text="全部" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/stroke_grey" />
<RadioButton
android:id="@+id/rb_doc"
style="@style/RadioButtonStyle"
android:text="DOC" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/stroke_grey" />
<RadioButton
android:id="@+id/rb_xls"
style="@style/RadioButtonStyle"
android:text="XLS" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/stroke_grey" />
<RadioButton
android:id="@+id/rb_ppt"
style="@style/RadioButtonStyle"
android:text="PPT" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/stroke_grey" />
<RadioButton
android:id="@+id/rb_pdf"
style="@style/RadioButtonStyle"
android:text="PDF" />
</RadioGroup>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/main_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/rg_foot"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
如上所示上滑隐藏下滑呼出效果已经实现,唯一要注意的是:
很多案例中负责滑动的子view都是recycleview,基本没有出现listview或者GridView的身影,原因就在于listview或者GridView的不具备recycleView的某些属性,不能够唤起父布局CoordinatorLayout去通知某个View做隐藏或者显示的动作。那么这一问题这么解决呢?Google提供了一个专门的属性去通知CoordinatorLayout子View的滑动状态。
android:nestedScrollingEnabled="true" ------有些许遗憾的是该属性要求api 21以上也就是安卓5.0,否则无法生效。当然你可以用recycleview来替代。
现在探讨另一个问题:tablayout来回滑动导致fragment重复加载应用崩溃的问题。
有关viewpagerAdapter的缓存机制:http://blog.csdn.net/android_cyw/article/details/54632112 ;讲解的很细致,不甚了解的可以去看看
我们都知道tablayout大多是结合viewpager实现滑动导航,而viewpager的fragmentpageradapter(适用于viewpager装载fragment的情况)会缓存fragment,来回滑动fragment调用attach方法绘制视图导致内部报裹的fragment重新添加,但是缓存导致没有执行onDestroy和onDetach方法,重新add就会导致重复添加子fragment导致应用崩溃。下面通过改造适配器解决这一问题,该适配器还能解决viewpager来回滑动可能出现的fragment空白页的问题(当然使用FragmentPagerStateAdapter替换fragmentpageradapter应该也是可行的,但是缓存效果就没有了)
package com.dcg.explore.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
public class BooksVPAdapter extends PagerAdapter {
private Fragment[] fragments;
private FragmentManager fm;
public BooksVPAdapter(FragmentManager fm, Fragment[] fragments) {
this.fm = fm;
this.fragments = fragments;
}
@Override
public int getCount() {
return fragments == null ? 0 : fragments.length;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = fragments[position];
if (!fragment.isAdded()) {
FragmentTransaction ft = fm.beginTransaction();
ft.add(fragment, fragment.getClass().getName());
ft.commitAllowingStateLoss();
fm.executePendingTransactions();
}
View view = fragment.getView();
if (view != null && view.getParent() == null) {
container.addView(view);
}
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(fragments[position].getView());
}
}