一只羊的blog


Android Fragment

Fragment的自定义属性

我们可以在layout中来定义一个fragment,系统会自动的去加载layout文件中指定的fragment类,这个功能实在非常的方便。目前我们再深入一步:如果我们想通过layout文件,来为fragment设置一些自定义参数怎么办呢?比如说women想在layout文件中,指定这个fragment应该加载哪个布局文件。下面我们来仔细看一下怎么来实现这个功能。

首先我们需要创建res/values/attrs.xml文件,文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="FragmentOne">          
        <attr name="extraInformation" format="string" />
        <attr name="fraction" format="fraction" />
    </declare-styleable>
</resources>

在这个文件中,我们为类FragmentOne设置了两个自定义属性,属性的类型分别为string、fraction。

Activity的布局文件-activity_hello_fragment.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:baselineAligned="false" >

    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.ingphone.hellofragment.FragmentOne"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:extraInformation="custom attr ok"
        app:fraction="100%"
        tools:ignore="MissingPrefix" />

    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.ingphone.hellofragment.FragmentTwo"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

第3行指定了一个命名空间:app,内容是http://schemas.android.com/apk/res-auto;看到网上有人说可以写成http://schemas.android.com/apk/ + package name的形式,我试了试,不成功。

15、16行为我们的自定义属性设置值。

17行为让Lint忽略15、16行引起的错误,在eclipse下面,15、16行会报错,无法编译,但是其实是可以编译的,如果不加17行,也可以在修改完这个布局文件后,clean project,也不会有错误。

最后一步就是在fragment的类中,读取这些属性-FragmentOne.java:

package com.ingphone.hellofragment;

import com.example.hellofragment.R;

import android.app.Activity;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragmentOne extends Fragment {
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstance) {
		return inflater.inflate(R.layout.activity_fragment_two, container,
				false);
	}

	@Override
	public void onInflate(Activity activity, AttributeSet attrs,
			Bundle savedInstanceState) {
		super.onInflate(activity, attrs, savedInstanceState);
		Log.v("HelloFragmentArguments", "onInflate called");

		TypedArray a = activity.obtainStyledAttributes(attrs,
				R.styleable.FragmentOne);

		CharSequence myString = a
				.getText(R.styleable.FragmentOne_extraInformation);
		if (myString != null) {
			Log.e("HelloFragmentArguments",
					"My String Received : " + myString.toString());
		}
		
		float mFraction = a.getFraction(R.styleable.FragmentOne_fraction, 1, 1, 0);
		Log.e("HelloFragmentArguments", "fraction is " + mFraction);

		a.recycle();
	}

}

只要实现onInflate这个函数就OK了。

完整的项目代码请见HelloFragmentArguments