Defining your own subclass of LayoutInflater.Factory seems a lot of work me. Simply override the Activity's onCreateView() with some generic code:
@Override public View onCreateView(String name, Context context, AttributeSet attrs) { View view; // No need wasting microseconds getting the inflater every time. // This method gets called a great many times. // Better still define these instance variables in onCreate() if (mInflator == null){ mInflator = LayoutInflater.from(context); mPrefix = ((Activity) context).getComponentName().getClassName(); // Take off the package name including the last period // and look for custom views in the same directory. mPrefix = mPrefix.substring(0, mPrefix.lastIndexOf(".")+1); } // Don't bother if 'a path' is already specified. if (name.indexOf('.') > -1) return null; try{ view = mInflator.createView(name, mPrefix, attrs); } catch (ClassNotFoundException e) { view = null; } catch (InflateException e) { view = null; } // Returning null is no big deal. The super class will continue the inflation. return view; }
Note the custom views must reside in the same package (i.e. in the same directory) as this activity, but then it's just a generic piece of code you can slap in any activity (or even better, inherit from a custom parent activity class). You're not worried about looking out for a particular class as specified in the solution offered by kcoppock:
if (MyCustomView.class.getSimpleName().equals(name)) {....
You're certainly not creating a whole new class.
The real magic is in the core library class, LayoutInflator.java. See the call, mPrivateFactory.onCreateView(), below?:
if (view == null && mPrivateFactory != null) { view = mPrivateFactory.onCreateView(parent, name, mContext, attrs); } if (view == null) { if (-1 == name.indexOf('.')) { view = onCreateView(parent, name, attrs); } else { view = createView(name, null, attrs); } }
You see, if the so called, mPrivateFactory, returns null (mPrivateFactory happens to be your activity class by the way), the LayoutInflator just carries on with it's other alternative approach and continues the inflation:
if (view == null) { if (-1 == name.indexOf('.')) { view = onCreateView(parent, name, attrs); } else { view = createView(name, null, attrs); } }
It's a good idea to 'walk through' the library classes with your IDE debugger and really see how Android works. :)
Notice the code,if (-1 == name.indexOf('.')) {, is for you guys who still insist on putting in the full path with your custom views, <com.wehavelongdomainname.android.ui.MyButton> If there is a 'dot' in the name, then the creatview() is called with the prefix (the second parameter) as null: view = createView(name, null, attrs);
Why I use this approach is because I have found there were times when the package name is moved (i.e. changed) during initial development. However, unlike package name changes performed within the java code itself, the compiler does not catch such changes and discrepancies now present in any XML files. Using this approach, now it doesn't have to.
Cheers.