How to replace a view after I've inflated? - android

I have built my interface by using ViewStubs, which I inflate during onCreate.
But later in my app, I want to change the View completely, by loading different View into the same place. How do I achieve that?

Remove the old View via removeView(). Then inflate and add the replacement via addView().
Though if you're going to be bouncing back and forth a lot, consider using a FrameLayout or ViewFlipper or something to have both views loaded at once, only making one visible.

Related

Android - Is a ViewStub worth it?

I have a ListView where each row of the listview contains about 10 ImageButtons. Most of these buttons have visibility = Gone and only show up in very rare scenarios. I am wondering if it's worth it to replace these ImageButtons with ViewStubs to avoid loading them (and the images they contain) all the time for all the rows of the listview. Then again their visibility is set to "Gone", so I am not sure what impact loading them has. Do their images actually get loaded or not?
Note that I am talking about replacing e.g. the 8 ImageButtons with 8 ViewStubs, not with 1
Cheers
A ViewStub is a dumb and lightweight view. It has no dimension, it does not draw anything and does not participate in the layout in any way. This means a ViewStub is very cheap to inflate and very cheap to keep in a view hierarchy. A ViewStub can be best described as a lazy include. The layout referenced by a ViewStub is inflated and added to the user interface only when you decide so.
Sometimes your layout might require complex views that are rarely used. Whether they are item details, progress indicators, or undo messages, you can reduce memory usage and speed up rendering by loading the views only when they are needed.
Simply a ViewStub is used to increase efficiency of rendering layout. By using ViewStub, manually views can be created but not added to view hierarchy. At the runtime, can be easily inflated, while ViewStub is inflated, the content of the viewstub will be replaced the defined layout in the viewstub.
The ViewStub will be loaded only when you actually use it/need it, i.e., when you set its visibility to VISIBLE (actually visible) or INVISIBLE (still not visible, but its size isn't 0 any more). ViewStub a nice optimization because you could have a complex layout with tons of small views or headers anywhere, and still have your Activity load up really fast. Once you use one of those views, it'll be loaded.
You must add ViewStub in Layout at first, after you can inflate it to another View.
Note: One drawback of ViewStub is that it doesn’t currently support the <merge/> tag in the layouts to be inflated. Alos ViewStub can’t be used more than once. Also keeping long-lived reference to a ViewStub is unnecessary, if it is required, it's good practice to null it after inflating, so GC can eat it.
Let's suppose your ViewStub ID is view_stub. You need to do the following in the activity:
ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);
View inflatedView = viewStub.inflate();
ImageButton button = (ImageButton) inflatedView.findViewById(R.id.button);
Now you can do whatever you want with the button :) That is, the inflate method returns the stub layout which contains the actual elements from the XML file.
Of course, you can always have the onClick XML attribute or can be dynamically called.
Is a ViewStub worth it?
->For the scenarios that you are specifying, I think `ViewStub` will be worth-shot.
See below urls about ViewStub
http://android-developers.blogspot.in/2009/03/android-layout-tricks-3-optimize-with.html
http://developer.android.com/reference/android/view/ViewStub.html
http://developer.android.com/training/improving-layouts/loading-ondemand.html
Instead of ViewStub you can try <\include> tag. The <include/> will just include the xml contents in your base xml file as if the whole thing was just a single big file. It's a nice way to share layout parts between different layouts.
Difference between <include> and <ViewStub> in android
Edit: just noticed that Endzeit commented regarding a similar direction before me.
I would start by doing some benchmarking around the inflating code with and without the views - just comment out the adapter code so it doesn't try to access the non existing views.
If the removal of the Views from the layout does gives you an improvement that you think is necessary and since you say the views are present only in rare scenarios which you are anyway checking for in your adapter,
then instead of inflating those views or even using view stubs, create them in code and add/remove them as needed (using the viewholder to reference them).
You could even go further and do a lazy creation of these views, similar to lazy loading of images, but I would only do that after running some benchmarking again.
I would use ViewStubs for loading complex layouts not simple ImageButtons.
Edit 2:
Looking into ViewStub inflate command, which is what it does when it needs to be visible you can see it infaltes the layout given and then adds it to the parent layout - since you are adding a simple ImageButton you can gain performance by not having a ViewStub and just adding the ImageButton in your code.
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/ViewStub.java#ViewStub.inflate%28%29
According to Google's official documentation here.
ViewStub is a lightweight view with no dimension that doesn’t draw anything or participate in the layout. As such, it's cheap to inflate and cheap to leave in a view hierarchy. Each ViewStub simply needs to include the android:layout attribute to specify the layout to inflate.
To experiment this, I created a sample project and added a ViewStub to the layout hierarchy. On running layout inspector I can see that all the layout attributes for ViewStub are zero.
Let's compare it to having a layout which has 10 buttons hidden. What this actually means is, the layout hierarchy has 10 buttons hidden, which is sitting in the layout hierarchy and taking up some amount of memory. It's cheap to leave a ViewStub in hierarchy since it doesn't take up much memory, at the same time it's cheap to inflate.
My final verdict would be, use ViewStub extensively when you've complicated views which are inflated rarely as it definitely helps in saving memory and improving View inflating time.
Using the Android monitor's Memory tab in Android Studio (button for the Android monitor should be at the bottom bar), you could check it yourself:
Take a look at the memory usage when running the app with invisible buttons
Take a look at the memory usage when running the app with visible buttons
If there is any difference, then you can conclude not everything is preloaded when the views are Gone. Of course, you could also compare this to a ViewStub implementation to check whether that will help to decrease memory usage.
In short, using custom view instead of viewstub.
We are having a similar situation now, and we have also tried viewstub before, listview works a little faster. But when it comes to 8 viewstubs, i don't think its a good idea to use viewstub to avoid inflate too many widgets.
Since u (and also us) have a logic to control whether 10 buttons to show or not , why not just define a custom view, and draw different buttons according to different state machine? It's much fast, and need no inflation at all, and it's logic is much better controlled. We are using this method to accelerate listview now and it works good.
when you set a view visibility to gone this means that This view is invisible, and it doesn't take any space for layout but its data are loaded into it.
Now the ListViews they remove the unseen or lets say the views that are out of the screen bounds for performance reasons .
A ViewStub is an invisible, zero-sized View that can be used to lazily inflate layout resources at runtime.
So i think if you want from my opinion I prefer the Views with GONE Visibility rather than using much logic with ViewStub and Creating and inflating ... etc .
But on the other hand
The rendering performance comes into picture when you are inflating
the views.
My guess is that its much cheaper to inflate a ViewStub than to
inflate a View, either from XML or by changing visibility. ViewStub is
especially used when you need to add/remove (indefinite) views (eg.
add phone numbers to a given contact). Hope this is what you were
looking for.
reference : ViewStub vs. View.GONE
some good Brief presentation of DDMS here :
http://magicmicky.github.io/android_development/benchmark-using-traceview/
Use ViewStub instead ImageButton.
This is because
. ViewStub is zero sized view by default while image button not
. View Stub is naturally an invisible view . its performance is better than image button because it load runtime only when its state become visible.

Is it OK to add multiple views to root view of an Activity?

It may sound foolish, but I actually can't find anything on it.
Is it ok to add multiple views to the root view of activity in Android?
So for example I could go like this:
setContentView(R.layout.main);
setContentView(gLView);
setContentView(otherView);
Or simply retrieve it as a view
FrameLayout layout = (FrameLayout)this.getWindow().getDecorView().findViewById(android.R.id.content);
layout.addView(view1);
layout.addView(view2);
layout.addView(view3);
layout.addView(view4);
It all seems to work on devices I test, but is it guaranteed to work on all of them?
Or should I artificially create single FrameLayout to add to root view and add everything to this FrameLayout?
More experiments:
1) if I don't use setContentView and print:
Log.d("Test", this.getWindow().getDecorView().findViewById(android.R.id.content).getClass().getName());
I get: android.widget.FrameLayout
2) If I set content view to for example GLSurfaceView and print the same Log.d
It also prints android.widget.FrameLayout
3) And if I dont' use setContentView at all, and simply do
FrameLayout layout = (FrameLayout)this.getWindow().getDecorView().findViewById(android.R.id.content);
layout.addView(myView);
It attaches the view
So I assume that android.R.id.content returns not what you set by setContentView but the parent of what you set, or the actual root view in activity (which turns out is FrameLayout?)
And I am able to add multiple children to it this way, but question is:
Am I allowed to do that?
Yes, it's perfectly fine to add multiple content Views at the root level. The content Views are simply added to a FrameLayout container, and it is best practice to simply use it for your layout if a FrameLayout is all you require for it, instead of adding an additional container layer.
If you are adding a new content View, then you should use the addContentView() method instead of setContentView(), which would cause the existing content to be replaced instead.
Also, it is possible to add multiple Views to the content container in XML layouts as well by using the <merge> tag, which would just replace the base FrameLayout.
Calling setContentView several times will simply replace whatever view you set before. So what you want to do is create a root view that contains the multiple views you want to add and set the root view to your Activity with setContentView. Your second example with the FrameLayout is a good approach.
Your approach is valid at some extent. but its nice practice to call the setcontentView() once in activity.
this is because it will be very easy to maintain the Activity life cycle and reduce the app crash due to layout leak.
I personally call the setcontentView() once. I define all the layout in single XML file. Afterwords I call setVisibility(View.VISIBLE) and setVisibility(View.INVISIBLE) or setVisibility(View.GONE) to show or hide any particular layout containing my certain views.
Edit
Also its very easy to adjust the layout in XML because you can use simple drag and drop and If you are using relativeLayout then it will be very easy to place any view any where. but in Java code its some how difficult to place the views on your desired position
Hope this helps :)

View Flipping in Android using same activity

I am new to android therefore I got a little bit lost with all those ViewFlipper, ViewSwitcher, ViewAnimator and ViewPager. Moreover, I am not sure what's happening under the hood.
Basically I have an activity which shows some data. With swipe (or button, doesnt matter) I would like to scroll the view and get to another page (as seen in the picture below).
Is it possible to implement something like that without changing to another activity?
I am a little bit confused regarding views and access to the design elements. How those pages are located each to another? e.g. If I am currently seeing Page1, can I modify content of Page3? Or plainly saying, are all page views loaded all together? As if I set setContentView(R.layout.xlayout); then I can access only xlayout elements.
But if I use same activity, then I have a thread there which updates a counter on Page1, if I change view to Page 2, the counter will not find Page1 Counter TextView and will complain.
As I Understand Android 4.0 has ViewPager which is similar to the seen in the picture. I am using GB. Should I use support library or can I just go around and implement something similar without importing any libraries?
(Sorry, my description is a little bit messy)
Yes, you can use ViewSwitcher, ViewFlipper and ImageSwitcher depending on your requirements.
ViewSwitcher may have two childs at max. And these child might be a View or an object of subclass of view.
ViewFlipper: May have as many childs you want. and these child might be a View or an object of subclass of view.
ImageSwitcher might be used to switch images over.
By using view flipper you can display one item at a time, and adding a gesture overlay, you can apply sliding effect. To apply View Flipper, you need to add all the views to ViewFlipper, and showNext and showPrevious methods are used to show next and previous child.
You need to use a ViewPager to have the same behaviour as in Google Play.
it only available on recent version of Android, but you can use the Compatibility Package to make it available for older version.
With a ViewFlipper you can't "scroll" between two pages.

Android view animation: replacing view by itself

In my android app, I have a notion of "trails": a sequence of objects that the user can navigate. The same view, naturally, is used to display all objects, just updating components (texts, images, etc.) when the next object is to be shown.
Now, I want to animate the transition between objects: when the user navigates from an object to the next object, I want to use the slide animation from right to left (and the other way around). The issue is that I don't have two views to animate between - only one view. Therefore when I try to animate displaying this view (when the next object is to be loaded), the visible view disappears, I get a blank screen - and then the view slides in from the right.
What I want instead is to have the existing view to slide out and be replaced by a new view (same View but with different content) to slide in from the right.
How should I go about it?
Looks to me like a combination of LayoutTransition and GestureDetector. You might even a ViewFlipper in there too.
The LayoutTransition has an animation feature you might want to look into.
I haven't been able to figure out how to use LayoutTransition in my case, so instead of having my View, I replaced it with ViewFlipper containing two copies of my View. When I need to replace the view with another, I keep track of which of the two is currently displayed, then update the other off-screen and then use standard "slide-from-left" and "slide-from-right" animation with showNext(). This is more complicated than I really wanted it to be and uses more memory, but it does the job.
The solution turned out to be very simple: ViewPager. I provide PageAdapter, which returns two similar views (same layout, different content) and ViewPager takes care of the rest. If I wanted to disable the swipe page changes, all I had to do is extend ViewPager, override onInterseptTouchListener and return false.

Changing the content view dynamically

I am new to android and am trying to figure out how to change the contentView at will.
Right now, I have a TableLayout in the content view and it was set using the setContentView(TableLayout) method.
However, if I wanted to change this contentview within the same activity, how would I invoke this? Would I simply invoke the same method like: setContentView(TableLayout2) or would I need to clear the screen first?
What is the procedure for staying within the same activity and changing the content on the screen?
Thanks!
This answer might help.
No, you can't call it multiple times
easily. You either need to entirely
remove all views and then inflate the
new layout, or use a ViewFlipper (or
FrameLayout) to switch between
different views.

Categories

Resources