I'm trying to make simple program that allows to "load" an .xml file and display it as the View in setContentView of a new activity. Basically, what I would like is that the view of the new activity would be the same as if I called
setContentView(R.layout.my_view)
where R.layout.my_view would be that xml file. But in my case, that file doesn't yet exist at compilation time, and should be loaded dynamically (e.g., from storage).
I guess I could parse my .xml file and build the view dynamically by code, but that feels like reinventing the wheel and it's also most likely that the views won't be identical. I thought there should be some easy way to do this, but all the methods I found so far from similar questions (e.g.,
getResources().getXml(R.layout.my_view);
//or
LayoutInflater.from(context).inflate(R.layout.my_view, null) )
seem to require the file already in compilation time. Is there something I'm missing?
well, its not possible to load XML from server and parse it like usual layout XML. from LatourInflater doc:
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.
and it isn't related to generating IDs or similar mechanism, just performance - so consider that you really need this feature, it is kind of blocked for a reason ;)
but if you still really want to load layout from third party you can use json2view lib. good luck!
It is impossible as you describe. But you can do it by Java code.
When we create a layout xml file under layout resource folder and give some id using android:id="#+id/textview" IDE generate an ID R.java file that hold all IDs we assign.
When we call that view from Activity or Fragment we create an Object using that ID like
TextView textview = (TextView) findViewById(R.id.textview);
and user that.
If you want to load xml code form storage or server as a plan text in xml format. You will assign some ID for your views. But IDE won't generate any ID for that. So you can not create object of them.
So solution is you have to generate view by Java code that means programmatically.
setContentView(R.layout.activity_main);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
width = width - (100/width)*80;
LinearLayout layout = (LinearLayout) findViewById(R.id.lo_dynamic_view_container);
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
TextView tv = new TextView(this);
tv.setLayoutParams(lparams);
tv.setWidth(width);
float redious [] = { 0, 0, 8.3f, 8.5f, 8.2f, 8.9f, 0, 0 };
ShapeDrawable shape = new ShapeDrawable (new RoundRectShape(redious,null,null));
shape.getPaint().setColor(Color.GREEN);
tv.setBackground(shape);
layout.addView(tv);
Here activity_main.xml will have only one empty LinearLayout layout. You can generate view according to your condition or instruction document form storage or server and add them to LinearLayout.
Related
I need to dynamically add text to a linear layout in an Android PdfDocument that I generate from a layout.xml file. The header is consistent and therefore placed in the layout. However, the data that follows comes from a few dynamically populated lists. I need to add this data using the Android PdfDocument library (no third party solutions please).
I have been able to create the Pdf and save it to external storage. I can changed the text of items defined in the layout.xml. I just can't add anything to the layout.xml dynamically.
My code is long and scattered over a few class as the PdfDocument is populated by a custom ReportBuilder object. So I will simply list the steps I take and show the relevant portion of my code.
This works:
1. Get layout and inflate it.
2. Create PdfDocument object.page object.
3. Set page width and height.
4. Get canvas.
...
// Get the canvas we need to draw on.
Canvas canvas = page.getCanvas();
// Set report title, text field already exists in report_layout.xml
// So this works
setPageTitle("Report Title");
// Adding dynamically generated content does not work here...
TextView text = new TextView(mContext);
text.setTextColor(BLACK);
text.setText("Testing if I can add text to linear layout report_container");
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
// The report container is an empty LinearLayout
// present in report_layout.xml
LinearLayout cont = mReportLayout.findViewById(R.id.report_container);
((LinearLayout)cont).addView(text);
// Draw the view into the pdf document
mReportLayout.draw(canvas);
// Finalize the page.
mDocument.finishPage(page);
// Return document, calling party will save it.
return mDocument;
...
As stated, anything that is already contained in the report_layout.xml file can have it's properties changed and is contained in the final pdf. However, the TextView I create and try to add is never visible. I have made sure text color is correct, I get no errors, I have tried placing images as well and that does not work either. What am I missing?
The problem is your linearlayout still has a width and height of zero.
Try to add:
//add this before mReportLayout.draw(canvas)
int measuredWidth = View.MeasureSpec.makeMeasureSpec(page.getCanvas().getWidth(), View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(page.getCanvas().getHeight(), View.MeasureSpec.EXACTLY);
mReportLayout.measure(measuredWidth, measuredHeight);
mReportLayout.layout(0, 0, measureWidth, measuredHeight);
Also take a look at this answer.
I want to set dynamic layout which is not present in resource like res or values.If it is present in my file-manager and i want to set that layout as a view layout.Is it possible to set dynamic layout to the views, without building app.I want to send the layout from the server and download the layout and set for the view without building and not from the resources.Is Butter knife used for this process or it's just for binding views to the variables.
Try Proteus
Proteus is meant to be a drop-in replacement for Android’s LayoutInflater; but unlike the compiled XML layouts bundled in the APK, Proteus inflates layouts at runtime.
With Proteus, you can control your Apps layout from the backend (no WebViews). Forget the boilerplate code to findViewById, cast it to a TextView, and then setText(). Proteus has runtime data bindings and formatters. Plugin in your own custom views and attributes and formatters.
p.s. large parts of Flipart is built using proteus
Butter knife used only for view binding.For this process you need fetch XML file from storage and then convert it into the view and then set as your layout.
No, you can't send layout file from the server and inflate it dynamically. All views in Android have IDs mapped in R.java file. You can't and shouldn't modify it manually.
Butterknife is used for View Binding and help to reduce findViewById boilerplate. You can't use Butterknife to add Views.
However, you can dynamically create views using Java code and add them to any container layout. eg You can add a button to a Linear layout like this.
ViewGroup linearLayout = (ViewGroup) findViewById(R.id.linearLayoutID);
Button someButton = new Button(this);
someButton .setText("A Button");
someButton .setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT));
linerLayout.addView(someButton );
I want solution of following:
I have create xml file in data/data/com.example.file/files/abc.xml so during running of app how I get this abc.xml in res/layout and should display on screen.
Thanks.
In general, the XML vocabulary for declaring UI elements closely
follows the structure and naming of the classes and methods, where
element names correspond to class names and attribute names correspond
to methods.
Courtesy goes to #Mike M : You cant create this .XML files used for layouts are pre-compiled .
I'm not sure I have followed your question- are you trying to attach a child view to the RelativeLayout? If so you want to do something along the lines of:
RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
View child = getLayoutInflater().inflate(R.layout.child, null);
item.addView(child);
the RelativeLayout item will be the container for your child view.
Your question needs to be a bit more specific, but here's a general answer:
If you are using fragments then you should re-create your fragment and then use:
inflater.inflate(R.layout.abc, container, false);
If you are using activities then you should use:
setOnContentView(abc);
I'm wondering if anyone can shed some insight as to the best practice for dynamically creating controls (inflate vs instantiate).
Inflate:
TextView styledText = (TextView)inflater.inflate(R.layout.styledTextView);
Instantiate:
TextView styledText = new TextView(mContext);
styledText.setTextAppearance(R.style.StyledTextStyle);
The object being created can either contain attributes in the inflated XML file, or be contained in a Style definition which is added to the instantiated object afterwards. (Assume that this styling includes width, background, text color, etc).
Haven't been able to run any time/memory tests of each method, was wondering if anyone knew which was quickest/most efficient.
LayoutInflator has a slight overhead because it has to parse xml in order to build the object. It also temporarily takes more memory for the same reason. Other than that, it builds the View object in the same manner that you would anyway. It may be something to worry about if you call it hundreds of times a second for some reason. 99.9% of the time though you'll never know the difference.
Also to note, any method that accepts an xml resource like "setTextAppearance" will have the same xml parsing overhead. The only difference in the examples you provided is it's not parsing the TextView xml, but it would still have to parse the style attributes.
Though this post asks about controls specifically, I think it's relevant to note that .. for working with a layout you want to dynamically create/add, I found in using the new (aka instantiate) approach , I was not able to get a reference to an inner ImageButton element that was defined in the xml file for which I instantiate the layout object reference.
When I use the inflate approach, the ImageButton was present upon reference.
So in my case:
Works :)
LayoutInflater inflater = LayoutInflater.from(getActivity());
CardView myCardView = (CardView) inflater.inflate(R.layout.my_cardview, null);
ImageView icon = (ImageView) myCardView.findViewById(R.id.iconId);
~~~~~~~~~~~~
Don't Work :( .. variable icon is null in this case
CardView myCardView = new CardView(getActivity());
ImageView icon = (ImageView) myCardView.findViewById(R.id.iconId);
I want to design the layouts programatically that means without the xml file as per project requirement.
But the terms used programatically is completely different from xml file.Is their any useful tutorial to learn programatically that means without xml file. guide me!
you can create any view you want
a linear layout
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
A Text View
final TextView tv = new TextView(this);
tv.setBackgroundColor(0xFFFF00FF);
tv.setTextColor(0xFF000000);
tv.setTypeface(null, Typeface.BOLD);
tv.setText("Where is Fred?");
tv.setGravity(Gravity.CENTER_HORIZONTAL);
and anything else.
Source
I advise you to spend some time learning about the View class and its popular subclasses such as LinearLayout, RelativeLayout, and so on. (Also, spend a bit of time looking at Drawables.)
When you're creating a layout using XML, you're using XML to define a hierarchy of View objects which, at runtime, are "inflated" into a real hierarchy of View objects that the XML layout file describes. For example, your first XML layout file might be a simple LinearLayout that contains a TextView (note I'm simplifying it for brevity):
<LinearLayout ... >
<TextView ... />
</LinearLayout>
In your Activity you would use this layout using setContentView().
All that XML file is doing is providing a specification, if you like, about the View structure that the system needs to build (or inflate) for you. The end result is that there will be a real LinearLayout object (which is a subclass of View) that has a reference a child TextView (again a subclass of View) together with suitable layout parameters.
To do the above programmatically (i.e. by creating instances of objects and using their methods, rather than inflating from XML) you might do something like (again simplified):
LinearLayout container = new LinearLayout(this);
TextView tv = new TextView(this);
tv.setText("hello");
container.addChild(tv); // Simple example - usually you'd specify layout parameters
setContentView(container);
The basic point I'm making is that, in really simple terms, a layout XML file can be thought of as a kind of 'script' that you can use to tell the system how to create a hierarchy of Views. You can create exactly the same result by programmatically creating instances of View objects and calling appropriate methods on them. Whichever route you take, the end result is the same: a bunch of View objects in memory that represent a View hierarchy.
What you will find is that XML layout attribute names aren't necessarily the same as the corresponding method names, but you can use the relevant API documentation to see what corresponding XML attribute strings are for given methods. For instance, the API documentation for LinearLayout details all of the methods as well as the XML attributes.