Fragment(優化佈局)

Fragment android

Fragment中文解釋能夠理解爲「碎片」,Activity的碎片app

一個Activity能夠有多個Fragment,一個Frgament能夠在多個Activity中ide

Fragment能夠看做是一個Activity。佈局

Fragment也能夠看做爲Activity的一個控件。優化

 

爲何Fragment能夠看做是一個Activity?this

Fragment的生命週期與Activity相似 spa

 

Fragment的生命周 3d

 

          

 

二,與Activity生命週期的對比code

 

     

就是多了onAttach()與Activity關聯時調用,只調用一次      onDetach()與Activity失去關聯時調用,只調用一次xml

onCreateView() 插入Activity時調用,只調用一次  onDestoryView()移除Activity時調用,只調用一次

onActivityCreatde()Activity的onCreate()方法發生時調用

 

 

爲何說Fragment相對與一個控件呢?

其實Fragment的一個重要做用就是把佈局文件變成一個View對象,而後把View對象插入到Activity中

怎麼把佈局變成View對象呢?

1 public class MyFragment extends Fragment{
2     @Override
3     public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
4         View view = inflater.inflate(R.layout.fragment, container, false);    
5         return view;
6     }
7 }

這樣就能夠實現把R.layout.fragment佈局文件變成view對象並在建立MyFragment對象時返回,至關與把這個佈局變成了一個自定義的控件

而後就能夠在咱們的另一個佈局文件中直接用咱們的View對象。把這個佈局插入到Activity類中。

在xml文件中加入這個控件就能夠了,注意必定要定義id,和name,name屬性爲Fragement類的具體位置(包名.類名)

1 <fragment 
2          android:id="@+id/fragment"
3          android:layout_width="wrap_content"
4          android:layout_height="wrap_content"
5          android:name="com.example.z_fragment.MyFragment"/>

這個效果就和咱們以前講過的自定義控件的一個方法同樣。代碼以下

 1 <include layout="@layout/fragment" 2 android:layout_width="wrap_content" 3 android:layout_height="wrap_content"/> 

效果是如出一轍的。

這種方法叫靜態加載

因此固然咱們也能夠和以前自定義控件同樣,再Activity中實現自定義控件裏面的小控件的響應事件,用<fragment>還能再Fragment中設置。

<include>方法是在Activity文件種直接findViewById這些控件,fragment也能夠這樣在Activity種findViewById。

還能夠在fragment類種定義,不過findViewById方法要在View對象中實現,例如:

 1 public class MyFragment extends Fragment{
 2     private Button bt;
 3     public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
 4         View view = inflater.inflate(R.layout.fragment, container, false);
 5         bt = (Button)view.findViewById(R.id.btf);
 6         bt.setOnClickListener(new OnClickListener() {
 7             public void onClick(View v) {
 8             }
 9         });    
10         return view;
11     }
12 }

不過值得注意的是,若是fragment中定義了響應的具體事件,Activity中也定義了,這樣的話會只執行Activity中的響應。

 

說完了靜態加載,固然也有動態加載拉。

動態加載則須要使用FragmentManger類中的事務   經過事務的add(),remove(),replace()等方法,添加,刪除,替換Fragment對象。

 
 
1                 MyFragment fragment = new MyFragment();
2                 //加載frgament
3                 FragmentManager fragmentManger = getFragmentManager();//Fragment管理器
4                 FragmentTransaction beginTransaction = fragmentManger.beginTransaction();//Fragment事務
5                 beginTransaction.add(R.id.line, fragment);//添加Fragment
6                 beginTransaction.addToBackStack(null);//把命令加載到棧
7                 beginTransaction.commit();//加載棧中的事務
 
 

 

 

上面的代碼是把fragment對象加載到Activity佈局文件中的中的一個編號爲(R.id.line)的線性佈局當中。

這樣咱們就能夠在應用進行的時候隨時插入或者移出frgament,或者控

 

提及隨時插入或者移出控件還有一種方法(ViewStub標籤)

1       <ViewStub 
2          android:id="@+id/vs"
3          android:layout ="@layout/fragment""
4          android:layout_width="wrap_content"
5          android:layout_height="wrap_content"/>

而後經過實例化這個控件,經過它的inflate()惰性加載的方法把裏面的東西顯示出來

其實控件自身也有隱藏的屬性,android:visibility=「gone」就是隱藏,而後調用方法變成「visbe」就不隱藏。

 

說到這裏,順便說一些佈局注意事項把,咱們用佈局的時候儘可能多用線性佈局和相對佈局 LinearLayout和RelativeLayout。

nergae標籤能夠把控件組合起來:

例如:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <ProgressBar
 7         android:id="@+id/progressBar1"
 8         style="?android:attr/progressBarStyleLarge"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content" />
11     <TextView
12         android:id="@+id/textView1"
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:text="TextView" />  
16 </LinearLayout>
是這樣的
 
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <merge xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <ProgressBar
 7         android:id="@+id/progressBar1"
 8         style="?android:attr/progressBarStyleLarge"
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content" />
11     <TextView
12         android:id="@+id/textView1"
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:text="TextView" />  
16 </merge>

至關與一個禎佈局。

 

好,讓咱們回到Fragment的最後一個知識點,Fragment與Activity通訊。

(1)Fragment可調用getActivity()方法獲取它所在的Activity

(2)Activity可調用FragmentManager的findFrgamentById()或findFragmentByTah()方法獲取Fragment

(3)Activity ->Frgament:在Activity中建立Bundle數據包,並調用Fragment的setArgument(Bundle bundle)方法

(4)Fragment ->Activity:須要在Fragment中定義一個內部會調接口,再讓包含該Fragment的Activity實現該回調接口。這樣Fragment能夠用該回調方法將數據傳遞給Activity。

 

實現3:

在Activity中:

1                 MyFragment fragment = new MyFragment();
2                 String text = et.getText().toString();
3                 Bundle bundle = new Bundle();
4                 bundle.putString("text", text);//"text"是bundle內部的信息的標識名
5                 fragment.setArguments(bundle);

在Fragment中: 

1 //Fragment.getArguments方法獲取傳遞過來的bundle對象的信息標識名爲「text」的數據 2 String text = getArguments().getString("text");//"text"是bundle內部的信息的標識名 

 

實現4:

在Fragment中:

(定義內部接口)

1 private String s="收到了";
2     private MyListener listener;
3     public interface MyListener{
4         public void get(String s);
5     }
6     public void onAttach(Activity activity){
7         listener =(MyListener)activity;//把Activity強制變成自定義接口
8         super.onAttach(activity);
9     }

而後在onCreateView中調用自定義接口的get方法:listener.get(s);

在Activity中:

鏈接自定義接口,實現get方法:

 1 @Override 2 public void get(String s) { 3 tv.setText(s); 4 } 

 

下面我用一個案例來總結上面所學的知識:

這個app定義了兩個Activity和兩個Fragment

第一個MianActivity包含兩個按鈕一個是靜態加載,一個是動態加載,有一個EditText和TextView用來與MyFragment通訊,還有一個Linerlayout用來放動態加載的Fragment

第二個MainActivtiy2靜態加載了MyFragemnt,Myfragemnt有一個按鈕,在MianActivity2實現了響應事件

第一個MyFragment關鍵是有一個按鈕,用來實現動態加載響應後切換到MyFragment2,還有一個TextView用來與MainActivity通訊

第二個MyFragment2關鍵是有一個按鈕,用ViewStud墮態加載fragment。

示例代碼:

MianActivity:

public class MainActivity extends Activity implements MyListener{
    private Button bt1,bt2;
    private EditText et;
    private TextView tv;
    private int n=0;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bt1 = (Button)findViewById(R.id.button1);
        bt2 = (Button)findViewById(R.id.button2);
        et = (EditText)findViewById(R.id.et);
        tv = (TextView)findViewById(R.id.tv);
        //靜態加載按鈕
        bt1.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,MainActivity2.class);
                startActivity(intent);
            }
        });   
        //動態加載按鈕
        bt2.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                n++;
                MyFragment fragment = new MyFragment();
                //向fragment中發送信息
                String text = et.getText().toString();
                Bundle bundle = new Bundle();
                bundle.putString("text", text);//"text"是bundle內部的信息的標識名
                ////Fragment.setArguments方法發送bundle對象給Activity
                fragment.setArguments(bundle);
                //加載frgament
                FragmentManager fragmentManger = getFragmentManager();//Fragment管理器
                FragmentTransaction beginTransaction = fragmentManger.beginTransaction();//Fragment事務
                if(n==1)
                    beginTransaction.add(R.id.line, fragment);//添加Fragment
                else
                    beginTransaction.replace(R.id.line, fragment);//替換Fragment
                beginTransaction.addToBackStack(null);//把命令加載到棧
                beginTransaction.commit();//加載棧中的事務
            }
        });
    }

    @Override
    public void get(String s) {
        tv.setText(s);
    }
}

MainAtivity2:

public class MainActivity2 extends Activity {

    private Button bt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        bt = (Button)findViewById(R.id.btf);
        bt.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                 Toast toast = Toast.makeText(MainActivity2.this, "被點了", Toast.LENGTH_SHORT);                    
                 toast.show(); 
            }
        });    
    }
}

MyFragment:

public class MyFragment extends Fragment{
    private Button bt;
    private TextView tv;
    
    private String s="收到了";
    private MyListener listener;
    public interface MyListener{
        public void get(String s);
    }
    public void onAttach(Activity activity){
        listener =(MyListener)activity;//把Activity強制變成自定義接口
        super.onAttach(activity);
    }
    
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment, container, false);
        bt = (Button)view.findViewById(R.id.btf);
        tv = (TextView)view.findViewById(R.id.tvf1);
        //Fragment.getArguments方法獲取傳遞過來的bundle對象的信息標識名爲「text」的數據
        String text = getArguments().getString("text");//"text"是bundle內部的信息的標識名
        tv.setText(text);
        listener.get(s);
        //點擊按鈕切換另一個MyFragment2
        bt.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                MyFragment2 fragment = new MyFragment2();
                FragmentManager fragmentManger = getFragmentManager();
                FragmentTransaction beginTransaction = fragmentManger.beginTransaction();
                beginTransaction.replace(R.id.line, fragment);
                beginTransaction.addToBackStack(null);
                beginTransaction.commit();
            }
        });    
        return view;
    }
}

MyFragment2:

public class MyFragment2 extends Fragment{
    private Button bt;
    private ViewStub vs;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View view = inflater.inflate(R.layout.fragment2, container, false);
        bt = (Button)view.findViewById(R.id.btf2);
        vs = (ViewStub)view.findViewById(R.id.vs);
        bt.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                vs.inflate();
            }
        });
        return view;
    }
}

MainAtivity界面:

MianAtivity2和MyFragment2的界面:(其中MyFragmnet2隱藏了一個MyFragemnt界面)

MyFragmet2的界面

運行結果:

  

    

  由於這只是示例的例子,因此沒用優化,第五張圖的上面的改變按鈕是按不了的,由於隱藏的控件已經出來了,再按程序會崩潰

第二個按鈕是沒有響應事件的,由於它是直接調用佈局,沒用再MainActivitiy中設置隱藏控件的子控件的響應。

雖然再MyFragment中有設置,可是它沒用調用MyFragment,而是直接調用佈局。

include也是一樣道理,可是fragment卻不一樣,由於它是佈局調用MyFragment對象。

 

 

若是有什麼錯誤,或者我理解錯誤或不當的,懇請你們糾正,謝謝!嘻嘻嘻

相關文章
相關標籤/搜索