I'd like to define custom attributes in Android fragment using XML (without using bundle additional parameters) like declare-styleable
in custom controls. But there are no constructors with AttrSet parameters, so is it possible? Can i just override public void onInflate(android.app.Activity activity, android.util.AttributeSet attrs, android.os.Bundle savedInstanceState)
in order to get attributes support?
Asked
Active
Viewed 1.7k times
37

Anton
- 1,903
- 3
- 16
- 18
-
Getting errors while compiling: `...\app\res\layout\select_category.xml:26: error: No resource identifier found for attribute 'showRadioButtons' in package 'com.companyX.projectY' ...\app\res\layout\select_category.xml:26: error: No resource identifier found for attribute 'highlightSelection' in package 'com.companyX.projectY' ...\app\res\layout\select_category.xml:26: error: No resource identifier found for attribute 'unselectedColor' in package 'com.companyX.projectY'` – Anton Dec 27 '11 at 06:54
-
app xml namespace and declare-stylable are written correctly. can provide them, if needed – Anton Dec 27 '11 at 06:57
2 Answers
91
The Link for Support4Demos is changed or can be changed so posting the complete solution. Here it goes.
Create attrs.xml file in res/values folder. Or add the below content if file already exists.
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyFragment"> <attr name="my_string" format="string"/> <attr name="my_integer" format="integer"/> </declare-styleable>
Override the onInflate delegate of fragment and read attributes in it
/** * 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); Log.v(TAG,"onInflate called"); TypedArray a = activity.obtainStyledAttributes(attrs,R.styleable.MyFragment); CharSequence myString = a.getText(R.styleable.MyFragment_my_string); if(myString != null) { Log.v(TAG, "My String Received : " + myString.toString()); } int myInteger = a.getInt(R.styleable.AdFragment_my_integer, -1); if(myInteger != -1) { Log.v(TAG,"My Integer Received :" + myInteger); } a.recycle(); }
Pass these attributes in your layout file as following. Just an example
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is android activity" /> <fragment android:id="@+id/ad_fragment" android:name="com.yourapp.packagename.MyFragment" android:layout_width="fill_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" app:my_string="Hello This is HardCoded String. Don't use me" app:my_integer="30" /> </RelativeLayout>
Thats all. Its a working solution.
While doing this if you see any namespace error in xml. try project cleaning again and again. This is pathetic but Eclipse and adt misbehaves sometimes.

starball
- 20,030
- 7
- 43
- 238

Rohit Sharma
- 13,787
- 8
- 57
- 72
-
2My Android Studio kept showing the custom attributes in XML with red underline indicating there is an error, but the whole project built just fine. FYI for someone who might think that they aint doing it right looking at those error in their layout file. – Pocha Nov 04 '14 at 06:37
-
2you can use `http://schemas.android.com/apk/res-auto` instead of xmlns:app="http://schemas.android.com/apk/res/com.yourapp.packagename" to auto-substitute package name. http://stackoverflow.com/questions/10448006/xml-namespace-declaration-auto-substitute-package-name – Helin Wang Nov 18 '14 at 02:06
-
OK I've missed that one before. If you, like me, copy pasted this from a couple of places, pay attention and make sure the namespaces match, e.g. **xmlns:${NameSpace}** and same in the attribute **${NameSpace}**:attribute="..." – TacB0sS Nov 27 '14 at 21:43
-
2Android Studio shows that `onInflate(Activity activity ...` is deprecated. You can use new handler like this (Kotlin): `override fun onInflate(context: Context?, attrs: AttributeSet?, savedInstanceState: Bundle?) { super.onInflate(context, attrs, savedInstanceState) val styledAttributes = context?.obtainStyledAttributes(attrs, R.styleable.MyFragment_my_string) val text = styledAttributes?.getText(R.styleable.MyFragment_my_string) styledAttributes?.recycle() }` – Vitalii Aug 12 '18 at 14:34
1
@Override
public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
super.onInflate(activity, attrs, savedInstanceState);
// Your code here to process the attributes
}

theelfismike
- 1,621
- 12
- 18
-
2Works, but make sure to clear Lint markers (Android Tools > Clear Lint Markers). I spent 10mn trying to figure out why it was not building! – tdevaux Aug 11 '13 at 00:28
-
3Thanks tdevaux, I only spent 5 minutes before re-reading this. I have 5 more minutes available in my life! – dhaag23 May 15 '14 at 01:18