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对象。
若是有什么错误,或者我理解错误或不当的,恳请你们纠正,谢谢!嘻嘻嘻