Custom LayoutInflater

Using custom UI libraries has one downside – in xml you have to write the full package name of each View. Android widgets can be used without full name. It’s also possible with custom Views – all we have to do is to replace the default LayoutInflater.

Some time ago my friend showed me a nice library called Calligraphy. The most interesting thing about it is that it adds its attributes to existing Android Views without any custom widgets. After a while with the code I found out how they achieved that and how I can use that techinique to quickly replace Android widgets with Carbon ones.

Let’s start with such layout:
ContextWrapper2

The trick Android does is very simple. If a class doesn’t have any prefix, add ‘android.widget.’ and then try to load it. We can easily create such loader for our package name:

public class CarbonLayoutInflater extends LayoutInflater {
    protected CarbonLayoutInflater(LayoutInflater original, Context newContext) {
        super(original, newContext);
    }

    @Override
    public LayoutInflater cloneInContext(Context newContext) {
        return new CarbonLayoutInflater(this, newContext);
    }

    @Override
    protected View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
        if (Character.isUpperCase(name.charAt(0)))
            return createView(name, "carbon.widget.", attrs);
        return super.onCreateView(name, attrs);
    }
}

This class is very simple and does exactly what I wrote in the previous paraghaph. How to use it? We need a ContextWrapper class which would return our Inflater as an inflater service:

public class CarbonContextWrapper extends ContextWrapper {
    private CarbonLayoutInflater mInflater;

    public CarbonContextWrapper(Context base) {
        super(base);
    }

    @Override
    public Object getSystemService(String name) {
        if (LAYOUT_INFLATER_SERVICE.equals(name)) {
            if (mInflater == null) {
                mInflater = new CarbonLayoutInflater(LayoutInflater.from(getBaseContext()), this);
            }
            return mInflater;
        }
        return super.getSystemService(name);
    }
}

Now all we have to do is to attach our wrapper. Like this:

public class ContextWrapperActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contextwrapper);
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(new CarbonContextWrapper(newBase));
    }
}

Since now, each packageless component will be resolved as a carbon.widget.*. Check out our layout with CarbonContextWrapper attached: ContextWrapper
What Calligraphy does is much more complex, but I don’t really need that. Their technique gave me an idea to try to mess with ContextWrapper and LayoutInflater. Carbon has a good number of widgets which can replace Android ones. With custom LayoutInflater you can quickly move to Carbon without replacing all Views in your layouts.

3 responses to “Custom LayoutInflater

  1. Kiruwka Moklyuk's avatarKiruwka Moklyuk July 4, 2015 at 9:47 pm

    Sorry for posting anonymously above, please remove the comment.

    Somehow this does not work, crashing with : `Binary XML file line #29: Error inflating class ViewStub`. (of course there is no ViewStub in the layout xml). Any ideas ?

    Like

  2. Kiruwka Moklyuk's avatarKiruwka Moklyuk July 4, 2015 at 10:12 pm

    ok, due to some investigation and looking at “hidden” implementation of onCreatView in com.android.internal.policy.impl.PhoneLayoutInflater my conclusion is that although a great idea but the approach in this post won’t work, unless some extra hacks are involved.

    Like

    • Zielony's avatarZielony July 5, 2015 at 12:25 pm

      You’re right – this is just an idea. Works with as simple case as shown above πŸ™‚ Each Android version behaves a little bit different, my sample doesn’t support View classes without match, etc.

      Would you like to present your findings? It may be very useful for me and others πŸ™‚

      Like

Leave a comment

Design a site like this with WordPress.com
Get started