今天在網上看到了一個開源庫:Spruce Android Animation Library (and iOS)javascript
也就是
html
你們會說這個關Fragment的什麼事,別急,聽我慢慢來講。java
咱們來能夠下載它的Demo文件:android
上面Gif的圖片裏面的界面,是RecyclerActivity.java
,而他引用的佈局是recycler_fragment.xml
。git
咱們先來看佈局文件recycler_fragment.xml
:github
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_fragment"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar android:id="@+id/recycler_tool_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/LightToolbarTheme" android:background="@color/colorPrimary"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>複製代碼
沒錯,你們一看就知道,和上面的Gif圖顯示的同樣,一個ToolBar,而後下面一個RecycleView,外面的ViewGroup是LinearLayout。app
原本是沒什麼問題的,可是我發現,他在這個界面加了一個Fragment。ide
在activity裏面的onCreate方法中:佈局
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_fragment);
FragmentManager fm = getSupportFragmentManager();
Fragment recyclerFragment = fm.findFragmentById(R.id.recycler_fragment);
if (recyclerFragment == null) {
recyclerFragment = RecyclerFragment.newInstance();
fm.beginTransaction()
.replace(R.id.recycler_fragment, recyclerFragment)
.commit();
}
......
......
......
}複製代碼
沒錯,他把這個Fragment,經過replace(R.id.recycler_fragment, recyclerFragment).commit()
,添加到了id 爲R.id.recycler_fragmnt
處,而這個R.id.recycler_fragmnt
就是咱們上面的activity佈局中的最外面的LinearLayout
。WHAT!!!不是通常都是加到FrameLayout
中的嗎???spa
而後咱們繼續看咱們加的RecyclerFragment.java
中的代碼:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) {
recyclerView = (RecyclerView) container.findViewById(R.id.recycler);
recyclerView.setHasFixedSize(true);
RelativeLayout placeholder = (RelativeLayout) container.findViewById(R.id.placeholder_view);
....
....
....
List<RelativeLayout> placeHolderList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
placeHolderList.add(placeholder);
}
recyclerView.setAdapter(new RecyclerAdapter(placeHolderList));
recyclerView.setLayoutManager(linearLayoutManager);
return inflater.inflate(R.layout.recycler_fragment, container, false);
}複製代碼
咱們發現了,這個fragment是對onCreate中的ViewGroup參數進行了操做,把他裏面的RecycleView作了處理,而後最後在return 了一個View,並且這個View的引用的佈局與咱們上面的Activity是同一個佈局文件!!!!都是recycle_fragment.xml。
這時候你是否是又有疑問了,通常在fragment中你們都是
View view = inflater.inflate(R.layout.recycler_fragment, container, false);
recycleView = (RecyclerView) view.findViewById(R.id.recycler);
...
...
return view;複製代碼
你有想過這個onCreate方法中的ViewGroup參數究竟是什麼,爲何這裏它能夠直接使用findViewById等。而後去對RecycleView作處理。那最後執行return inflater.inflate(R.layout.recycler_fragment, container, false);
這句話,並 沒有對其中的RecycleView作處理,豈不是這個這時候界面上顯示的RecycleView 顯示的是空的???
我新建一個Activity,他的佈局文件是:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/activity_linearlayout" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是Activity" /> </LinearLayout>複製代碼
再建一個Fragment,他的佈局文件是:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fragment_linearlayout"
>
<TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是Fragment" /> </LinearLayout>複製代碼
而後咱們把這個Fragment添加到Activity的最外面的LinearLayout中。咱們看下效果,以下圖
咱們發現被加進來的Fragment就像是一個控件同樣,依照LinearLayout的特性,垂直向下排了下來。也就是說咱們的在Activity中動態添加Fragmenet,並非只能加到FrameLayout
中,還能夠加到其餘ViewGrop中,可是爲何都是添加到FrameLayout
中呢。
解答:
在stackoverflow上找到相關提問。
Why is a FrameLayout used for fragments?
咱們在本身寫的這個Demo中的Fragment的oncreate方法中打印這個ViewGroup。會發現:
android.widget.LinearLayout{127e518 V.E...... ......I. 0,0-0,0 #7f0e0053 app:id/activity_linearlayout}複製代碼
能夠看到,這個ViewGroup就是咱們在把這個Fragment添加進Activity時候寫的id相對應的佈局。
爲何會這樣?
看下面的相關文章:
Android fragment源碼全解析
咱們就會知道containerViewId 最後就是咱們傳入的id值。
既然這個ViewGroup container就是咱們傳入的id對應的View ,即咱們的Activity佈局中的LinearLayout,咱們固然後直接對這個container經過findViewById來拿到裏面的相關控件。
最後咱們再回頭看上面那個開源項目的Demo。
在它的Fragment中的onCreate方法中的ViewGroup container其實就是他的Activity中最外面的LinearLayout的View。這個View裏面包括了ToolBar和RecycleView,因此能夠經過recyclerView = (RecyclerView) container.findViewById(R.id.recycler);
而後對RecycleView進行相關處理。
並且這裏的RecycleView,是Activity中自己佈局中的那個RecycleView。而後咱們也知道了,這時候添加到Activity的LinearLayout中的Fragment是排在原來的控件的下面。
就是說應該是:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_fragment"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar android:id="@+id/recycler_tool_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/LightToolbarTheme" android:background="@color/colorPrimary"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="match_parent" /> <!--這下面就是Fragment返回的View的內容--> <....> ... ... </....> </LinearLayout>複製代碼
因此這時候,其實真正顯示列表的原來Activity中的RecycleView,因此就算咱們把Fragment中的onCreateView裏面最後return null。也不會影響界面顯示。
那爲何Demo中Fragment返回了一個同Activity同樣的佈局內容的View,卻沒有顯示呢,由於咱們Activity中的RecycleView的高度是match_parent,若是咱們把它改成200dp,咱們就能看到效果:
果真fragment的內容就呈現出來了。由於咱們就是單純的return inflater.inflate(R.layout.recycler_fragment, container, false);
,而沒有作相關的處理,因此就是一個空的RecycleView,和一個沒內容的Toolbar。