ApiDemos--FragmentArguments的例子分析
FragmentArguments这个类向我们展示了两种向Fragment传递参数的方式,一种是在XML中使用属性传递参数,一种是动态地setArguments()方式来设置参数。我们先来看看这两种方式的不同。
1) 通过属性传递参数
此方式就是在XML布局文件设置某个属性来传递参数,通常的布局文件形式如下:
/layout/fragment_arguments.xml
<fragment class="com.example.android.apis.app.FragmentArguments$MyFragment"
android:id="@+id/embedded"
android:layout_width="0px" android:layout_height="wrap_content"
android:layout_weight="1" apidemos:arguments_label="@string/fragment_arguments_embedded" />
其中的apidemos:arguments_label就是要传递的属性值,当然apidemos是我们的自定义空间名字,arguments_label是我们自定义的属性值。apidemos这个值定义形式如下:
xmlns:apidemos="http://schemas.android.com/apk/res/com.example.android.apis"
即xmlns:<自定义空间名>="http://schemas.android.com/apk/res/<应用程序包名>"
那么自定义属性的值定义方法是,在/res/values/attrs.xml中如下定义:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="FragmentArguments">
<attr name="arguments_label" format="string" />
</declare-styleable>
</resources>
上面那个值”FragmentArguments”我们会在代码中用到,我们在其中定义了属性”arguments_label”,它的值是”string”类型。
1)动态地setArguments()形式
这个形式是在代码中实现的,通常形式如下:
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment newFragment = new Fragment();
newFragment.setArguments(…);
ft.add(R.id.container, newFragment);
ft.commit();
然后在某处调用Fragment.getArguments()就可以取得传递进来的参数,非常简单。
看过了上面的参数传递方式之后,如果你已经完全理解了,那么这篇文章你无须再看了。
现在开始分析FragmentArguments类,它的定义如下:
public class FragmentArguments extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_arguments);
/*如果发生屏幕翻转或者其他引起该Activity重建的事件,这个savedInstanceState就不为空,这个时候就不应该再ft.add Fragment了,因为重建时Framework会自动恢复视图层中的Fragment。*/
if (savedInstanceState == null) {
// First-time init; create fragment to embed in activity.
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment newFragment = MyFragment.newInstance("From Arguments");
ft.add(R.id.created, newFragment);
ft.commit();
}
}
}
在onCreate()中通过调用setContentView()设置了界面布局,布局文件中设置了属性参数,那么在MyFragment启动的时候,就可以读取这个属性值了,方法如下:
public static class MyFragment extends Fragment {
CharSequence mLabel;
/**
* Parse attributes during inflation from a view hierarchy into the
* arguments we handle.
*/
@Override public void onInflate(Activity activity, AttributeSet attrs,
Bundle savedInstanceState) {
super.onInflate(activity, attrs, savedInstanceState);
TypedArray a = activity.obtainStyledAttributes(attrs,
R.styleable.FragmentArguments);
mLabel = a.getText(R.styleable.FragmentArguments_arguments_label);
a.recycle();
}
}
通过在回调onInflate中调用TypedArray的get方法就可以获取对应的自定义属性的值。onInflate()在Fragment的生命周期中处于onAttach()之前。
在MyFragment的newInstance()中我们可以动态添加参数,代码如下:
/**
* Create a new instance of MyFragment that will be initialized
* with the given arguments.
*/
static MyFragment newInstance(CharSequence label) {
MyFragment f = new MyFragment();
Bundle b = new Bundle();
b.putCharSequence("label", label);
f.setArguments(b);
return f;
}
在它的onCreate()回调中就可以读取这个动态参数,代码如下:
/**
* During creation, if arguments have been supplied to the fragment
* then parse those out.
*/
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
mLabel = args.getCharSequence("label", mLabel);
}
}
然后把参数mLabel显示在屏幕中,我们就可以看到效果了。效果图如下:
当然了,如果旋转一下屏幕,效果略有不同:
之所以效果不同,是因为/res/layout-land/下也定义了布局文件Fragement_arguments.xml。
如果你对上面的TextView的带有白边的背景图疑惑的话,那么是因为TextView设置了自己的背景为android.R.drawable.gallery_thumb,那么这个gallery_thumb到底是什么样的drawable呢?在目录/sdk/platforms/android-19/data/res/drawable中有文件
gallery_thumb.xml,定义如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 The Android Open Source Project
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="@drawable/frame_gallery_thumb_selected" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/frame_gallery_thumb_pressed" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/frame_gallery_thumb_pressed" />
<item android:drawable="@drawable/frame_gallery_thumb" />
</selector>
原来这个drawable是个StateListDrawable,不同的状态下显示不同的图片,这些图片同样可以在同个文件夹或就近的位置找到,我把图贴出来方便大家查看吧。
frame_gallery_thumb_pressed.9.png
frame_gallery_thumb_selected.9.png
由于那个TextView是不可点击的,如果设置这个TextVie.setClickable(true);你就能看到效果了。