Load partial XML layout into ready layout for android - java

I am attempting to create a program with a set of dynamically loaded layout "pages". I have the base layout created with a minimal default skeleton of the Views common to each page. For each page I was going to hard code all the views to be swapped (:facepalm). My next thought was to create a text file and put the necessary data in a well formatted design. Only then I realized that's exactly what the XML files are. So what I would like to do is create an XML file of the pages with the data exactly as it would appear in the original layout file. Then as each page is loaded (possibly unload another page), pull the XML data for that page and insert it into the current base layout structure.
My page data
<?xml version="1.0" encoding="utf-8"?>
<pageList>
<page:1>
<Button .../>
<EditText .../>
</page>
<page:2>
...
</pagelist>
The base XML layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:weightSum="1">
<LinearLayout android:id="#+id/linearLayout1"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1.00" android:weightSum="1">
<EditText android:id="#+id/editText1" android:inputType="textMultiLine"
android:layout_width="0dp" android:layout_weight="0.30"
android:layout_height="match_parent"></EditText>
<RelativeLayout android:layout_width="0dp"
android:id="#+id/orientationLayout" android:layout_weight="0.70"
android:layout_height="match_parent">
<dynamically insert my PAGE here>
I am new to Android programming and have only a little experience in generating interfaces from XML. In programming C# and XML for a previous job, I would have to pull the data directly from an embedded XML file and use that to create the Button or TextBox myself. Do I need to do similar in this case or is there a way to automatically load it?
I have looked this up for a while and most answers I found on this site and other places are from months ago or longer. Those answers tend to range from IMPOSSIBLE to do it yourself. I'm hoping maybe in the past few months there might have been a change to the system I have yet to find.

You are probably looking for a ViewStub.
A ViewStub is an invisible, zero-sized View that can be used to lazily
inflate layout resources at runtime. When a ViewStub is made visible,
or when inflate() is invoked, the layout resource is inflated. The
ViewStub then replaces itself in its parent with the inflated View or
Views. [...]
You can use this like a normal view in your layout and use findViewById() to reference it in code. After that use ViewStub.setLayoutResource() to set layout that you want to show and call ViewStub.inflate() to show it. This way you can write a normal XML
layout file for every (sub-)page you need.
Also see this article.
Edit: Or probably not, I have to mention that the stub gets removed from the view hierachy after inflating. So, depends on your actual use case if this is helpful.

Related

Improving performance of instantiating and inflating views used with a ViewFlipper

I am using a ViewFlipper to display all the measurements the app has made (1 measurement = 1 page element). The problem is, the performance of initializing/reloading of the content of the ViewFlipper gets very bad if there are more then 50 elements. i.e., the app gets unresponsive for about 15 seconds after it has launched. I did some logging and found out, that more than 70% of the loading time is spent on View.inflate(ctx, R.layout.view_measurement, null);
From my understanding, inflate(...) does parse the layout xml file to a View so it can be used in Java. Since the layout xml file is everytime the same, it looks to me like there is the same heavy job being done for each element over and over again. I tried many things to change this and let this happen only one time, unfortunately without success. I also tried to use and tags in the xml also but always got errors.
I know that there are better ways rather than the ViewFlipper to do this job, but as I am in a hurry everything else works fine, I would like to keep this and find a fast solution.
MainActivity.java
...
ViewFlipper viewFlipper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewFlipper = (ViewFlipper)super.findViewById(R.id.measurementsViewFlipper);
int measurementsAmount = 100; //example
for(i=0; i<measurementsAmount; i++){
View measurementView = View.inflate(ctx, R.layout.view_measurement, null);
... fill the view ...
viewFlipper.add(measurementView);
}
...
}
view_measurement.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
...
</LinearLayout>
</RelativeLayout>
The only way to reduce the xml inflation time is to reduce the number of views used in the xml layout. For example, just by looking at he layout you posted, you could(and should) remove the root RelativeLayout if it's just wrapping the LinearLayout. Also, using ConstraintLayout might allow you further remove ViewGroups and reduce the nesting level and the view count.
But this will still not be ok because the real problem is you are inflating a lot of views upfront. In your example if the page layout contains just 5 views you'll create 500 views in total(100 x 5). That's a lot and this is why you need to have a view recycle mechanism so you don't need to create all views upfront, just a few for the current pages.
If you want ViewFlipper's behavior, the Android SDK has a component called AdapterViewFlipper which you should use instead. It just needs an additional adapter class, to which you'll pass the measurement data and in which you'll inflate the measurement layout.

How to use same XML layout in android to create several activities, each with their own custom view

New to coding to Android, but I couldn't find an answer to this particular problem. Say I have the following XML layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<view class="com.example.testapp.customView"
android:id="#+id/drawView"
android:layout_height="100dp"
android:layout_width="fill_parent" />
<Button android:id="#+id/bNormal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Update" />
</LinearLayout>
I want to use this layout to create several activities, but in each activity I want to use a different customView. Eg. for one activity I would like the custom view to be customView1, the second activity I would like it to be customView2, etc.
How would I go about doing that? Right now I just have a seperate XML layout for each of my activities, and this seems awfully redundant.
You either create several layouts, or you have to add the new view programatically (by creating an object of the proper type and adding it to the parent view) rather than doing it via xml. The idea behind xml layouts is that your layout is more or less static, so the xml specifies exactly what you want. It isn't meant to be a programming language itself where things can change.

Can multiple android views be stored in the same .xml file without belonging to the same parent?

I have an android project that has several small views which I need to instantiate at runtime. I haven't been able to figure out a way to store all of these related views in a single xml file and I now there are going to be many of these xml files. I was just wondering if there is any way to have them all in a single file, but not belonging to some parent ViewGroup.
The layout folder in android kinda sucks since there's no way to make subfolders, everything is just piled into the same place, ugh.
I hope someone can tell me of a better way of organizing these things.
If I understand you correctly you want several views meged onto one screen or merged into one xml file. You can include other xml's into one.
The articles showed you how to use the tag in XML layouts,
to reuse and share your layout code. This article explains the tag and how it complements the tag.
http://developer.android.com/resources/articles/layout-tricks-merge.html
Also, this video might help (about 19 minutes in). Shows you how to extract a current layout and be able to include it in others.
a couple things:
Yes, the layout folder is a pain. I use strict naming conventions to make it bearable, and in eclipse use the shortcut ctrl + shift + r to quickly find the layout I am looking for. Try naming your layouts after your activity: activity1_menu_overlay and activity1_main. With the above shortcut, just type out Activity1 and it will only show you the relevant layouts.
And if that doesn't work, you can try wrapping all your views in LinearLayouts and using view.setVisibility(View.Gone); or view.setVisibility(View.Visible); to show/hide the appropriate views.
Here is an example of that second one, because it's tough to explain.
one XML file:
<LinearLayout>
<LinearLayout ... android:visibility="visible">
<copy/paste of view 1>
</Linearlayout>
<Linearlayout ... android:visibility="gone">
<copy/paste of view 2>
</Linearlayout>
<Linearlayout ... android:visibility="gone">
<copy/paste of view 3>
</Linearlayout>
<Linearlayout ... android:visibility="gone">
<copy/paste of view etc.>
</Linearlayout>
</Linearlayout>
keep in mind this approach will require you to define a reference to each "child" LinearLayout view in your activity, so you can call setVisiblity appropriately.
This approach works well for animations, and I would only use it for 2 or 3 possible views in one xml file.

Virtual keypad is hiding data elements of the screen

I have an issue with a virtual keyboard.
This Soft Keyboard Covers Data Fields - and can't See what's going on.
I want to use this soft keypad and at the same time it should not become a problem to use data fields.
So how can I manage the data fields in such cases?
Encase the layout that you already have set up within a ScrollView. This will allow the content to scroll when the software keyboard shows. Keep in mind a ScrollView has to be formatted as such.
<Scrollview android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!-- Your content -->
</LinearLayout>
</ScrollView>
You may also consider setting the following attribute on your Activity in the Android Manifest to further specify the behavior.
From here (http://developer.android.com/guide/topics/manifest/activity-element.html):
android:windowSoftInputMode=["stateUnspecified",
"stateUnchanged", "stateHidden",
"stateAlwaysHidden", "stateVisible",
"stateAlwaysVisible", "adjustUnspecified",
"adjustResize", "adjustPan"]
I find that adjustResize works better for applications contained in ScrollViews in my particular case.

Android ExpandableListActivity issue

I want to customize my ExpandableList. My issue is that I need a button and expandable list on single activity. Can I achieve that? I have seen all the examples but all extends ExpandableListActivity not the Activity in which I can put all the widgets in one activity.
Any help would be appreciated.
According to the documentation this task should not be too hard.
the first thing that you will have to do is create a new xml file to hold your custom layout. The file should be saved in your res/layout folder and be named something like "my_custom_expandable_list_view_layout.xml", it should look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ExpandableListView android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<Button android:id="#id/my_button_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Click Me"/>
</LinearLayout>
The import part of that layout file is that you include an "ExpandableListView" and give it the id of "android"list".
The next thing that you will need to do is let your activity know that you are using a custom layout by calling setContentView() in your activities onCreate(). The call should look something like this
setContentView(R.layout.my_custom_expandable_list_view_layout);
At this point you should be able to run you program and see a large button at the bottom of the screen. In order to do something with this button you will need to access it via a call to findViewById() in your Activity like this
Button myButton = (Button)findViewById(R.id.my_button_id);
Once you have that myButton object you can add a click listener or whatever else you would like to do. You can pretty much add anything else you want by just adding new things to the layout file.

Categories