2

I'm trying to load an XML file created by user to use it in my app. I know that it's not possible to use the XML file as a resource because the layout files are compiled in building APK process. Is there anyway to use/create/load layouts on-the-fly outside the layout folder?

greywolf82
  • 21,813
  • 18
  • 54
  • 108

2 Answers2

3

You can create a XmlPullParser from your file and pass it to the layout inflater.

To create the XMLPullParser from your file you can follow this example: https://developer.android.com/reference/org/xmlpull/v1/XmlPullParser.html

And after having the XMLPullParser object, you can call this method: https://developer.android.com/reference/android/view/LayoutInflater.html#inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup)

You need an ViewGroup that will be the parent of the view. If you need the view to be an activity, I recommend that you create a empty activity with a layout and add the parsed layout to the empty layout. Don't try to inflate the layout without a parent, you can have distinct results in different devices.

jonathanrz
  • 4,206
  • 6
  • 35
  • 58
  • 1
    It's a notification layout actually, so no parent :/ – greywolf82 Dec 04 '16 at 18:51
  • 1
    @greywolf82 I saw that now the NotificationBuilder is expecting a RemoteViews. I think that you can create a RemoteViews from a empty layout file (just with the view group) and after use the addView(View) method to add the inflated view from the LayoutInflater. And you can use the RemoteViews as the parent. – jonathanrz Dec 04 '16 at 18:57
  • 2
    In the doc there is: Important For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime. – greywolf82 Dec 04 '16 at 19:01
  • @greywolf82 Oh, that's bad :(. I understand that can have some performance problem, but I think that android should accept a view inflation on the fly :/. The layout is complicated? Because you can make the parse by hand and add each View manually. – jonathanrz Dec 04 '16 at 19:03
  • 1
    I don't know actually because the layout should be user selected however add the View manually could be an option. The method you pointed out is not applicable :/ – greywolf82 Dec 04 '16 at 19:05
  • @greywolf82 I think that you can parse the layout with XMLParser creating an AtributeSet, here you can find more information: http://stackoverflow.com/questions/39558602/parse-an-android-xml-layout-file-using-xmlpullparser – jonathanrz Dec 04 '16 at 19:07
  • 1
    Tomorrow I'm going to try. Thanks. – greywolf82 Dec 04 '16 at 19:07
  • @greywolf82 nice, please return with the results :) – jonathanrz Dec 04 '16 at 19:12
  • @jonathanrz that requires it to be one of the pre-processed XML files. This still will not work with regular XML. – Karakuri Dec 04 '16 at 20:37
  • @Karakuri you are talking about the answer or the conversation here at the chat? – jonathanrz Dec 05 '16 at 00:20
  • @jonathanrz the link you posted is to another scenario where the files are pre-processed XML, not plain XML like the OP is using. – Karakuri Dec 05 '16 at 03:14
  • @Karakuri yep, but here in the comments we found another option. – jonathanrz Dec 05 '16 at 11:28
3

You cannot inflate arbitrary XML because XML files in Android projects get processed at build time and converted to a binary format. In other words, you can only build the layouts programmatically with the Java APIs.

What you can do is parse the user's file with a standard XML parser (e.g. XmlPullParser and build the views yourself. Basically you would be re-implementing LayoutInflater, which you can find the source code for online.

One thing to note is the user's XML won't be able to refer to resources at all. For example, they could not do something like android:textColor="@color/some_color". The build processing turns references like these into pointers to resource values, whereas if you were to simply read this in plain XML, it would just be the text "@color/some_color".

Perhaps instead of allowing users to create full-fledged Android layout XMLs, you should instead choose a limited subset of things you will support and define a simpler way of describing these custom layouts. Then you wouldn't have to use XML, you can define a custom "language" with just the things you want. This way you can limit the users to relatively simple APIs, like text color; you simply map some field defined in your custom language to a call to textView.setTextColor().

Karakuri
  • 38,365
  • 12
  • 84
  • 104
  • Hey man! Could you please explore this a bit further? Where would he save images for instance, if he wanted the layouts that user 1 creates to be shared by several users? – Pedro Pinheiro May 19 '20 at 21:44