时间:2012/11/14
书籍:Beginning.Android.4.Application.Development
开发环境:eclipse
1.FRAGMENTS
--一个应用通常占据整个屏幕,我们可以用mini-Activity来使布局在大屏幕和小屏幕之间切换的时候发生意料之外的改变。
--一个mini-Activity可以用于他自己的views,而一个活动可以拥有多个mini-Activity。
--Fragments是Activity的另一种形式,通常嵌在Activity当中,
例如在某个手机应用当中:
fragment1是一个list,而fragment2是一个textView或者ImageView,当你在fragment1选中一个list项的时候,fragment1就会转换到fragment2来显示该项目的信息。如果在平板上的话fragment1和2就会如下排布:
由于屏幕大了,所以fragment1和2可以并列排布,作用也如上面所述。
2.如何创建一个fragment
创建一个fragment跟创建一个Activity很类似--一个java文件+一个xml文件。xml文件用于处理UI布局,而java文件则用于处理交互逻辑。
(1)创建一个类并继承fragment类,如下:
(3)为了载入UI界面,要实现一个onCreateView的方法,如下:
public class Fragment1 extends Fragment {
}
(2)为fragment定义一个xml文件。
--正如上述中所说,要为fragment创建一个xml文件,用于加载UI元素,譬如在res/layout下创建一个fragment1.xml文件,其中如下:
<?xml version=”1.0” encoding=”utf-8”?>
<LinearLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:background=”#00FF00”
>
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”This is fragment #1”
android:textColor=”#000000”
android:textSize=”25sp” />
</LinearLayout>
这样就为fragment创建了一个独立的UI界面(当然可以嵌入到父窗体中)。
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
//---Inflate the layout for this fragment---
return inflater.inflate(
R.layout.fragment1, container, false);
}
onCreateView方法返回一个View对象,在方法里面,要用一个LayoutInflater对象的inflate方法来载入UI界面。而container则是一个ViewGroup对象,就是那个要将fragment镶嵌进去的Activity。savedInstanceState参数允许你恢复fragment先前的状态。
(4)在要嵌入fragment的Activity中加入fragment组件。正如在Activity中加入其他组件一样。如下:
<fragment
android:name=”net.learn2develop.Fragments.fragment1”
android:id=”@+id/fragment1”
android:layout_weight=”1”
android:layout_width=”0px”
android:layout_height=”match_parent” />
注意这里的android:name和fragment里面的参数是Package name.fragment name,在第一步中,创建的fragment1类在这里被指定。借此将此fragment和其对应的类结合起来。
这样就可以在主Activity中加入fragment窗体。
3.在活动中动态加入fragment。
--fragment主要的用于在于他能动态的在Activity中出现/隐藏。如下:
(1)在Activity中添加fragment,需要一个FragmentManager类,如下:
FragmentManager fragmentManager = getFragmentManager();
(2)为了在Activity中是fragment能转换,需要一个FragmentTransaction类,如下:
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
(3)有了上述两个之后,再通过windowManager来判断是在那个模式下,如下:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
//---get the current display info---
WindowManager wm = getWindowManager();
Display d = wm.getDefaultDisplay();
if (d.getWidth() > d.getHeight())
{
//---landscape mode---
Fragment1 fragment1 = new Fragment1();
// android.R.id.content refers to the content
// view of the activity
fragmentTransaction.replace(
android.R.id.content, fragment1);
}
else
{
//---portrait mode---
Fragment2 fragment2 = new Fragment2();
fragmentTransaction.replace(
android.R.id.content, fragment2);
}
fragmentTransaction.commit();
--首先要决定当前的mode是landscape还是portrait mode,决定了以后用fragmentTransaction对象的replace方法,此方法将特定的fragment加载到指定的view container(此处的fragment是fragment2,加载到的地方是R.id.content,也就是主Activity的容器)。设置好了以后用commit方法是改变生效即可。
4.Fragment组件的生命周期。
--正如活动一样,fragment也有他自己的生命周期。
(1)当创建时。
➤ onAttach()
➤ onCreate()
➤ onCreateView()
➤ onActivityCreated()
➤ onCreate()
➤ onCreateView()
➤ onActivityCreated()
这几个方法会顺序调用。
(2)当fragment界面被看见时。
➤ onStart()
➤ onResume()
➤ onResume()
这几个方法会顺序调用。
(3)当活动在后台运行时。
➤ onPause()
➤ onStop()
➤ onStop()
(4)当fragment所在的Activity被销毁时。
➤ onPause()
➤ onStop()
➤ onDestroyView()
➤ onDestroy()
➤ onDetach()
➤ onStop()
➤ onDestroyView()
➤ onDestroy()
➤ onDetach()
fragment的生命周期如上述。
(5)注意以下几点。
1.onAttached -- 在fragment跟父窗体联系的时候调用。
2.onCreateView -- 在fragment的UI创建时调用。
3.onActivityCreated -- 当Activity的onCreate方法return时调用
4.onDestroyView -- 当fragment的view被移除的时候调用(例子中的mode转换的时候)
5.onDetach -- 当fragment跟父活动丢失联系时调用。
5.在fragment中传递数据。
--可以用findViewById方法在一个fragment中读取另一个fragment中的数据,前提是要将要读取数据的控件都添加到Id中。
--假设有两个fragment,分别为fragment1和fragment2,定义如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#00FF00" > <TextView android:id=”@+id/lblFragment1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="This is fragment #1" android:textColor="#000000" android:textSize="25sp" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFE00"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="This is fragment #2!"
android:textColor="#000000"
android:textSize="25sp"
/>
<Button
android:id="@+id/btnGetText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="get text in fragment #1"
android:textColor="#000000"
android:minWidth="255px"
android:onClick="onClick"
/>
</LinearLayout>
现在要在fragment2按Button触发onClick读取fragment1中的TextView中的数据。那么onClick应该如下:
(1)如果在MainActivity.java.中添加的话:
public void onClick(View v) {
TextView lbl = (TextView)
getActivity().findViewById(R.id.lblFragment1);
Toast.makeText(getActivity(), lbl.getText(),
Toast.LENGTH_SHORT).show();
}
在主活动的java文件中可以直接声明一个方法,只需要名字和绑定改方法的组件一样(这里的onClick和BUtton中的android:onClick=“onClick”)即可。
(2)如果在fragment2.java(即用于提供fragment2交互的java文件中),则要通过添加listener的方法来将onClick方法和Button绑定。如下:
Button btnGetText = (Button)
getActivity().findViewById(R.id.btnGetText);
btnGetText.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView lbl = (TextView)
getActivity().findViewById(R.id.lblFragment1);
Toast.makeText(getActivity(), lbl.getText(),
Toast.LENGTH_SHORT).show();
}
}
通过Activity的findViewById方法,提供一个组件在定义中的android:id中的名字,就可以获得object,然后将其强制转换后得到该实体。获得实体后(上例中的btnGetText),可以通过其setOnClickListener方法来设置一个监听onClick动作的方法,上例中用了onClick方法来处理。当btnGetView被点击的时候,onClick方法就会被调用,而在onClick方法中也是用findViewById方法来获得lblFragment1组件(textView)的内容,随后用toast输出。
6.用intent来调用系统内置的应用。
--如果用intent来调用系统内部的功能--地图,拨号,浏览器等。
(1)在安卓系统内,intent对象一般以action和data的形式成对存在,action定义了应该干什么,而data则定义了应该用哪些数据去执行动作。而data一般用Uri类来传递。
(2)用intent对象传递数据,新建一个intent实例,如:
Intent i = new
Intent(android.content.Intent.ACTION_VIEW,
Uri.parse(“http://www.amazon.com”));
在构造方法中传入:1.要执行的活动,提供的名字在程序Manifest文件中的intent-filter标签中的action name指定。2.数据,新建一个uri对象,然后在里面传入所提供的数据,这里是提供了网址。
(3)将intent对象准备好了之后,就可以直接调用startActivity(Intent i)来调用活动。参数正是上一步弄好的Intent对象。
(4)一般常用的内置系统活动有。
(4)一般常用的内置系统活动有。
ACTION_VIEW -- (1)用来浏览网页,提供:“http://www.amazon.com”
(2)用来浏览地图,提供:“geo:37.827500,-122.481670”
注意提供的数据是http和geo。
ACTION_DIAL -- 用来拨打电话,提供:“tel:+651234567”
ACTION_PICK -- 用来选择一个从联系人列表中选择联系人。提供:"content://contacts".
ACTION_CALL -- 直接打电话。提供:“tel:+651234567”
等。
(5)也可以构造intent和传递数据分开,如下:
Intent i = new
Intent(“android.intent.action.VIEW”);
i.setData(Uri.parse(“http://www.amazon.com”));
startActivity(i);
这样就可以分别设置了。