Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Activities loading xml layout dynamically in android

Is it possible to load an activity's xml layout file from a resource stored in the device (in a db or part of the resources) and load it dynamically when that activity is started ? The idea is to send it to the device from a web service. Thanks.

like image 374
xain Avatar asked Mar 16 '11 12:03

xain


4 Answers

If you are trying to inflate a XML file that was not included during the build process I don't think it is currently possible. This is from the java-docs of the LayoutInflater class:

View android.view.LayoutInflater.inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)

Inflate a new view hierarchy from the specified XML node. Throws InflateException if there is an error.

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.

like image 51
theJosh Avatar answered Nov 17 '22 16:11

theJosh


As of the date of this posting, Android only contains a built-in way to inflate layout XML stored as a layout resource in the APK file. If you want to inflate similar (or different) XML from other sources, you will have to implement that yourself, perhaps by cloning some logic from the LayoutInflater class. Be warned that Android does a lot of work to optimize reading and parsing of resource files at run-time, so if you plan on loading this dynamically on your own, be prepared for it to inflate a LOT slower.

like image 23
Alex Lockwood Avatar answered Nov 17 '22 17:11

Alex Lockwood


If you have to load info from a db, maybe it helps you to do a basic XML, and insert info on it, like a table or something like that. You can try something like this:

In a basic table XML:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchColumns="1"
android:id="@+id/SensorInfoTableLayout">

<TableRow>
    <TextView
            android:text="@string/sensor_name_title"
            android:padding="3dip" /> 
    <TextView
            android:text="@string/sensor_type_title"
            android:padding="3dip" />
    <TextView
            android:text="@string/sensor_value_title"
            android:padding="3dip" />
    <TextView
            android:text="@string/sensor_unit_title"
            android:padding="3dip" />
</TableRow>

<View
    android:layout_height="4dip"
    android:background="#FF909090" /></TableLayout>

And the code:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); 

    getSensorInfo();
    setContentView(R.layout.sensorinfo);

    setInfoByView();
}

private void setInfoByView() {
    TableLayout myTableLayout = null;
    myTableLayout = (TableLayout)findViewById(R.id.SensorInfoTableLayout);

    // Add row to table
    myTableLayout.addView(createRow("maxRange",maxRangeType, "" + maxRange ,maxRangeUnits));
    myTableLayout.addView(createRow("minDelay",minDelayType,"" + minDelay, minDelayUnits));
    myTableLayout.addView(createRow("name",nameType,"" + name, nameUnits));
    myTableLayout.addView(createRow("powerReq",powerReqType,"" + powerReq, powerReqUnits));
    myTableLayout.addView(createRow("resolution",resolutionType,"" + resolution, resolutionUnits));
    myTableLayout.addView(createRow("type",typeType,"" + type, typeUnits));
    myTableLayout.addView(createRow("vendor",vendorType,"" + vendor, vendorUnits));
    myTableLayout.addView(createRow("version",versionType,"" + version, versionUnits));
}

private TableRow createRow(String name, String type, String value, String unit) {
    // Create new row
    TableRow myTableRow = new TableRow(this);
    myTableRow.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
    //myTableRow.setGravity(Gravity.CENTER_HORIZONTAL);
    myTableRow.setPadding(5, 5, 5, 5);
    // Add name
    myTableRow.addView(createTextView(name));
    // Add type
    myTableRow.addView(createTextView(type));
    // Add value
    myTableRow.addView(createTextView(value));
    // Add units
    myTableRow.addView(createTextView(unit));

    return myTableRow;
}

In the XML, it only exists the principal bar, with name, title, value and unit. And dinamically, add rows with info and style.

Maybe it helps, it works for me.

like image 3
vgonisanz Avatar answered Nov 17 '22 17:11

vgonisanz


The guys at flipkart have created an alternative for Android's LayoutInflater which accepts JSON, which can be hosted anywhere.And it also accepts optional data for data binding to native inflated views.

Sample JSON for View

{    
  "type": "LinearLayout",
  "orientation": "vertical",
  "padding": "16dp",
  "children": [{
    "layout_width": "200dp",
   "gravity": "center",
    "type": "TextView",
    "text": "@{user.profile.name}"
  }, {
    "type": "HorizontalProgressBar",
    "layout_width": "200dp",
    "layout_marginTop": "8dp",
    "max": 6000,
    "progress": "@{user.profile.experience}"
  }]
}

Sample Data JSON:

{
  "user": {
    "profile": {
      "name": "John Doe",
      "experience": 4192
    }
  }
}

And to dynamically Inflate: Use the ProteusView by including it in project:

ProteusView view = proteusLayoutInflater.inflate(<layout>, <data>);
container.addView(view.getAsView());

Here is an introduction by the authors themselves: https://www.slideshare.net/mobile/KiranKumar1320/proteus-android-layout-engine

Have a look at it here: https://github.com/flipkart-incubator/proteus/blob/master/README.md

like image 3
Harsh Sharma Avatar answered Nov 17 '22 16:11

Harsh Sharma