在前一次利用ViewPager實作仿微信Tab效果的後,又學習了利用Fragment實作該效果,剛好是對Fragment的一次學習了解。
效果圖就不展示了,和ViewPager的界面類似,唯一的缺點就是,利用單純的Fragment無法實作像ViewPager一樣的左右滑切換。就當做一次對Fragment的了解學習吧。
這個Demo的難點總結:
1.Fragment的了解與使用。
2.FragmentTransaction與Fragment生命周期的關系。
3.FragmentTransaction中不同操作的差別。(此處遇到問題!)
接下來來詳細闡述一下以上兩點:
一、Fragment的了解使用。
原來一直都是在書上看完了Fragment的使用,隻是知道Fragment的是用來在一個Activity中便于實作大量控件與事件的分類處理。利用這次機會剛好初步學習了一下Fragment的使用與了解。
http://blog.csdn.net/lmj623565791/article/details/37970961這篇大神的部落格已經很詳細的講解了有關Fragment的了解與使用。看完過後知道了Fragment的基礎使用方式兩種:
(1)靜态的使用Fragment
(2)動态的使用Fragment。
而本例中使用的就是第二種使用方式,利用FragmentTransaction實作動态使用Fragment。一開始還不了解動态的使用的含義,看完那篇部落格後,了解到,就是利用FragmentManager在Activity中操作Fragment。
也就是說在Activity中動态的管理Fragment。具體方式步驟如下:
1.定義自己的mFragment繼承Fragment(此處有一個要點就是:包名要一緻,如果導入的是android.app.Fragment後面導入的都要是app下的包例如android.app.FragmentManager;而如果導入的是android.support.v4.app.Fragment,後面要一緻導入v4包,不然會産生錯誤)。重寫onCreateView方法:如下
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("Tag", "onCreateView");
// TODO Auto-generated method stub
return inflater.inflate(R.layout.tab1, container, false);
}
2.擷取FragmentManage,利用getFragmentManager()(v4中,getSupportFragmentManager)得到FragmentManage。
3.開啟一個事務FragmentTransaction。
4.調用add(),show(),remove(),replace(),hide()等相關操作實作所需功能。
代碼如下:
MainActivity.java
package com.example.fragmenttab;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity implements OnClickListener{
private LinearLayout l1, l2, l3, l4;
private ImageView pic1, pic2, pic3, pic4;
private Fragment f1,f2,f3,f4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
initEvent();
setSelect();
}
private void initEvent() {
// TODO Auto-generated method stub
l1.setOnClickListener(this);
l2.setOnClickListener(this);
l3.setOnClickListener(this);
l4.setOnClickListener(this);
}
private void initView() {
// TODO Auto-generated method stub
l1 = (LinearLayout) findViewById(R.id.lin1);
l2 = (LinearLayout) findViewById(R.id.lin2);
l3 = (LinearLayout) findViewById(R.id.lin3);
l4 = (LinearLayout) findViewById(R.id.lin4);
pic1 = (ImageView) findViewById(R.id.pic1);
pic2 = (ImageView) findViewById(R.id.pic2);
pic3 = (ImageView) findViewById(R.id.pic3);
pic4 = (ImageView) findViewById(R.id.pic4);
}
private void setSelect(int i){
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
hideFragment(transaction);
switch (i) {
case :
if(f1 == null){
f1 = new OneFragment();
transaction.add(R.id.content, f1);
}else{
transaction.show(f1);
}
pic1.setImageResource(R.drawable.tab_weixin_pressed);
break;
case :
if(f2 == null){
f2 = new SecondFragment();
transaction.add(R.id.content, f2);
}else{
transaction.show(f2);
}
pic2.setImageResource(R.drawable.tab_find_frd_pressed);
break;
case :
if(f3 == null){
f3 = new ThirdFragment();
transaction.add(R.id.content, f3);
}else{
transaction.show(f3);
}
pic3.setImageResource(R.drawable.tab_address_pressed);
break;
case :
if(f4== null){
f4 = new FourthFragment();
transaction.add(R.id.content, f4);
}else{
transaction.show(f4);
}
pic4.setImageResource(R.drawable.tab_settings_pressed);
break;
}
transaction.commit();
}
private void hideFragment(FragmentTransaction transaction) {
//隐藏所有Fragment
if(f1 != null){
transaction.hide(f1);
}
if(f2 != null){
transaction.hide(f2);
}
if(f3 != null){
transaction.hide(f3);
}
if(f4 != null){
transaction.hide(f4);
}
}
@Override
public void onClick(View v) {
resetImage();
switch (v.getId()) {
case R.id.lin1:
setSelect();
break;
case R.id.lin2:
setSelect();
break;
case R.id.lin3:
setSelect();
break;
case R.id.lin4:
setSelect();
break;
}
}
private void resetImage() {
// 重置所有圖檔
pic1.setImageResource(R.drawable.tab_weixin_normal);
pic2.setImageResource(R.drawable.tab_find_frd_normal);
pic3.setImageResource(R.drawable.tab_address_normal);
pic4.setImageResource(R.drawable.tab_settings_normal);
}
}
OneFragment.java
package com.example.fragmenttab;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class OneFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("Tag", "onCreateView");
// TODO Auto-generated method stub
return inflater.inflate(R.layout.tab1, container, false);
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/top" />
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></FrameLayout>
<include layout="@layout/bottom" />
</LinearLayout>
其他界面和前一個例子相同。
以上就是這次所有的總結,這樣就結束了嗎?NO!NO!NO!
在這個例子中一個無意的操作引發了一個自己無法解決的問題。
問題如下:
在這個例子中原理就是,每次點選之前都回執行hideFragment()方法使用者将所有的Fragment利用transaction.hide()方法隐藏掉,然後再二次點選時利用show()方法顯示。這些看似很基礎,但是我一開始寫的時候,不小心将hide()方法寫成了remove()方法,這時候問題來了!!!運作效果是第一次點選都是好的,但是第二次點選後界面就為空白了。
問題原因:
設定斷點調試,發現原因很簡單,執行remove後,二次點選在這一步:
if(f1 == null){
f1 = new OneFragment();
transaction.add(R.id.content, f1);
}else{
transaction.show(f1);
}
這時f1不為null,執行show()方法,而f1已經被remove了是以show是空白。
但是看似簡單的問題原因,仔細一想,FragmentTransaction的remove方法定義是從Activity中移除一個Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧後面會詳細說),這個Fragment執行個體将會被銷毀。
銷毀?對,你沒有看錯,銷毀後不應該為null嗎?為什麼判斷的時候不是null哪?糾結啊,看了Fragment的源碼和FragmentTransaction的源碼還是無法了解原因,Tag了Fragment的生命周期發現,remove後确實執行了onDetach()方法,也就是說該Fragment已經的确被銷毀了,但是判null的時候不是null,糾結啊!!!希望有大神能解決這個問題啊。我自己也在尋找原因,希望下次部落格能夠發出解決貼吧!