简体   繁体   中英

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.

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.

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.

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.

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

Is it possible to load an activity's xml layout file from a resource stored in the device

Yes.

View inflatedView = View.inflate(this, R.layout.sample, null);
container.addView(inflatedView);

As @Chirag Raval said.

Is it possible to load an activity's xml layout file from a db / web service?

Don't think so. Because the layout reference (id) that you call from R.layout.XPTO is pre-compiled. You can't add values during runtime.


An middle-term option that you can use (and that I use in some apps) is set a pre-determined number o "blocks" that can be re-arranged according to the data that is sent.

Example:

Receive text, image, text + image

Load: text_block.xml then image_block.xml and then text_and_image_block.xml

It is not possible "out of the box" as explained in other answers, but the open source project ItsNat Droid makes a big effort to provide rendering of Android native XML based resources downloaded remotely (HTTP) similar to a "native Android" browser, native Android based XML instead of HTML and Beanshell scripting instead of JavaScript.

Obviously the performance is not going to be the same as local pre-compiled native resources. This is similar to comparing a web application to a desktop application, a web application is fine to most of needs but is not ok for games, in Android local/remote is very similar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM