I had to dig for a while (some 10 minutes) to get my android fragments to receive the attributes form the xml layout.
This is how I got it working.
Starting by with a fragment (I'm using Jake Burton's ActionBarSherlok but the same should work when extending the support or original fragment classes):
1: class MyOwnFragment extends extends SherlockFragment { 2: /* fragments attributes */ 3: private int padding = 8; // default value that will be overridden if there's a layout attributes 4: private String lavel = ""; // default value that will be overridden if there's a layout attributes 5: 6: @Override 7: public void onCreate (Bundle savedInstanceState) { 8: super.onCreate (savedInstanceState); 9: if (savedInstanceState != null) { 10: // use the saved state that was set in the #onSaveInstanceState 11: } 12: } 13: 14: @Override 15: public void onSaveInstanceState (Bundle outState) { 16: // save the state of our fragment into the outState bundle. 17: } 18: 19: 20: @Override 21: public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 22: View fragmentRootView = // what ever you need, inflate a layout, progamatically create a view, etc. 23: 24: // if there were attibutes in the layout XML 25: // then we would have captured them in the #onInflate method 26: // so we would already have them available 27: 28: // we can also use the savedInstanceState here 29: // to set child views of GroupView for example. 30: 31: return fragmentRootView; 32: } 33: 34: @Override 35: public void onInflate (Activity activity, AttributeSet attrs, Bundle savedInstanceState) { 36: super.onInflate (activity, attrs, savedInstanceState); 37: TypedArray typedArray = activity.obtainStyledAttributes(attrs, R.styleable.MyOwnFragment); 38: if (typedArray != null) { 39: // this is where we can get out attributes. 40: // we can "parse" them into class fields 41: this.padding = typedArray.getDimensionPixelSize (R.styleable.MyOwnFragment_padding, this.padding); 42: String labelAttr = typedArray.getString (R.styleable.MyOwnFragment_label); 43: if (labelAttr != null) { 44: this.label = labelAttr; 45: } 46: } else { 47: // no attributes are defined 48: } 49: } 50: }
The R.stylable.MyOwnFragment
is a reference to the styleable defined at res/attrs.xml
:
1: <?xml version="1.0" encoding="utf-8"?> 2: <resources> 3: <declare-styleable name="MyOwnFragment"> 4: <attr name="padding" format="dimension" /> 5: <attr name="label" format="string" /> 6: </declare-styleable> 7: </resources>
And finally in the layout file:
1: <?xml version="1.0" encoding="utf-8"?> 2: <RelativeLayout 3: xmlns:android="http://schemas.android.com/apk/res/android" 4: xmlns:app="http://schemas.android.com/apk/res/our.package.name" 5: android:layout_width="fill_parent" 6: android:layout_height="fill_parent"> 7: 8: <fragment android:name="our.package.name.MyOwnFragment" 9: android:id="@+id/myOwnFragment" 10: android:layout_width="wrap_content" 11: android:layout_height="wrap_content" 12: app:padding="2dp" 13: app:label="Fragment label" /> 14: </RelativeLayout>
Now the trick I had to find was that the we need to use the namespace of our application in the layout XML or it doesn't work (the attributes do not arrive at our fragment onInflate
method). The strange thing is that the android lint will then complain that the defined namespace is not used but if we ignore the warning everything works fine.
The Fragment
documentation and the sdk example are not very helpful. They reuse the android namespace but that seems not to work (for me at least) as then it complains that the attribute is not recognized.