Removing a View from an Activity - android

You've got a View defined in a layout file. How do you remove it from you Activity code?

ViewGroup vg = (ViewGroup)(myView.getParent());
vg.removeView(myView);
should do what you want as far as correctly removing the View from the Activity. The other guys' answer will just make the View invisible, using up resources.

As Android mentioned in a comment:
view.setVisibility(View.GONE);
Quoting the Android reference:
This view is invisible, and it doesn't take any space for layout purposes.
I think it's the best solution unless you really need to delete the object.

Related

Android Performance : Adding view programmatically vs setting view to GONE/VISIBLE

I'm working in a project that requires to inflate a simple tutorial View when the user opens the app for the first time. I'm trying to do it "the right way", and I'm wondering about performance issue.
Currently, I have in my layout a view sets to android:visibility="GONE", which I change to VISIBLE depending on a SharedPreference. This allows me to let the user learn how the app works on first launches.
What I'm wondering is what it implies when the view is rendered in my Fragment. My guess is that the view will be uselessly inflated, even if its visibility is set to GONE.
Now, I'm thinking about an alternative: what if I would only add my View on first launches, but programmatically, in my Fragment's onCreateView. That should allow the view not to be inflated on later launches, but wouldn't inflating the view programmatically implies bad performance on first launches?
So, to answer my own question I used the DDMS tool TraceView to monitor the calls from my fragment onAttach until its onResume. It let me see which implementation are the less efficient.
To do the test, I had a simple RelativeLayout with a FrameLayout inside it (shown all the time). I used a custom layout to add each time, either programmatically or with a visibility of GONE on my layout file. The custom layout was composed of a RelativeLayout with 4 childs (an ImageView, a TextView, a View, and a Button).
My onCreateView was the following, allowing the app to inflate the right layout based on two static final boolean constants to change the layouts.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
LinearLayout root;
if(INFLATE_PROGRAMMATICALY) {
root = (LinearLayout) inflater.inflate(R.layout.fragment_test_prgmcly, container, false);
if(SHOULD_FYI_VIEW_BE_SHOWN) {
View tutoView = inflater.inflate(R.layout.inner_view, root, false);
root.addView(tutoView);
}
} else {
root = (LinearLayout) inflater.inflate(R.layout.fragment_test_gone,container,false);
if(SHOULD_FYI_VIEW_BE_SHOWN) {
View tutoView = root.findViewById(R.id.RL_inner_view);
tutoView.setVisibility(View.VISIBLE);
}
}
return root;
}
This lead to the following results:
When the optional layout in inflated
SHOULD_FYI_VIEW_BE_SHOWN=true
The maximum "real time estimate" given by the TraceView are of 75ms when there is just a view to change from GONE to VISIBLE, but of 110ms when we need to instantiate the inner_view.
When the optional layout isn't inflated
SHOULD_FYI_VIEW_BE_SHOWN=false
In this case, the maximum real time estimate given by TraceView are of 102ms for the inflation of the GONE view, versus 39ms when the view inflated doesn't have the GONE view.
So, for the performance gain when the views doesn't need to be inflated, I'd say that the best solution is to inflate your view programmatically if you only need to show it a few time.
You can find the test project on a Gist
I think you are reinventing a wheel. For this scenario is already existing tool in Android xml layouts. It is called ViewStub. You can read more here: Loading ondemand
I think I just randomly stumbled over the answer of your performance question.
From the Animation Docs:
For the view that is being faded in, set its visibility to GONE. This
prevents the view from taking up layout space and omits it from layout
calculations, speeding up processing.
This would mean performance is not compromised as long as you don't set android:visibility to anything else than GONE.

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 :)

Adding Views to an Android Viewgroup Programmatically

This seems to be a common question yet documentation is very hard to find. I'm looking for examples that show me how to create my own view group (preferably by extending an already existing one) and then add views programmaticly.
Thanks.
ViewGroup
ViewGroup is abstract, and its onLayout is abstract too. So you need to provide an implementation for onLayout where you do assign a position at every child (View) of the viewgroup.

How to create View Stub?

I am new to android.. I have a slider in my xml. For the particular value of the slider I want an Image to appear and later disappear.. I heard that View Stub can do the trick.. But not exactly getting the solution.. Can any one please help me..
Thanks,
Keerthiraj
ViewStub is used when you have a "heavy" view which is hidden but may be shown later. ViewStub is a light-weight view which inflates the real view at run-time when it's made visible.
So ViewStub doesn't solve your problem. I thinks the best solution for you is to set ImageView's visibility:
imageView1.setVisibility(View.GONE);
imageView2.setVisibility(View.VISIBLE);

Which is the lightest view?

In Android, Which is the light weight view ?
ex:- View, Textview, Edittext, etc....
In some case we need to use a view to fill the area without showing the view to the user.
At the same time the screen should load fast.
You can use Space.
android.widget.Space
Space is a lightweight View subclass that may be used to create gaps between components in general purpose layouts.
If by "lightweight" you meant memory footprint, then there is none exists on Android, because each view have to derive from View, which itself is a massive object (well, not massive, it is about 8kB), so it's not that big.
But in terms of measure, layout and draw time the basic View performs well. You just have to set its visibility to INVISIBLE. And so it will be measured and put into the layout (contrary to GONE with which the view would not take up any space).
Unfortunately ViewStub is not meant to be used for this purpose. Its default visibility is GONE.
If you are really picky, then you can extend View and override methods like draw() (to do nothing, do not even call super), dispatchDraw(), setVillNotDraw(true), etc. (Take ViewStub as a sample).
You should have a look at ViewStub.
Use ViewStub if it is sufficient or LinearLayout which may be somewhat light weight.

Categories

Resources