I'm following the examples in a recent book (Learn OpenGL ES For Mobile Game and Graphics Development) and the suggestion made there is to programmatically add a new layout (let's call it settingsLayout) in the main activity and then:
LayoutInflater settingsInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View settingsLayoutView = settingsInflater.inflate(R.layout.mySettingsLayout,settingsLayout,false);
settingsLayout.addView(settingsLayoutView);
addContentView(settingsLayout,settingsLayoutParams);
This works fine, but I've added it to the callback for one of my action bar menu items, and I'd like to be able to remove this view when the back button is used. So far, that is causing me a lot of headache.
Meanwhile, it seems that the most natural way to implement dynamic views (addable to backstack, etc) is through Fragments. However, fragments need to belong to a layout, and currently my code assigns the GLSurfaceView directly as the content view for my main activity, without using a layout at all. Since GLSurfaceView is a subclass of View (and not View Group), I cannot use it to spawn children such as fragments.
The author of the book claims that this approach is "sleek", but doesn't give any other reason for assigning the GLSurfaceView directly as the content view. Is there a performance issue to be aware of? Or is it just as "sleek" to make a "master" layout to which both my GLSurfaceView and subsequently spawned views belong?
Is there some other even more natural way to get buttons, text boxes, etc. to dynamically appear and disappear on top of my GLSurfaceView?
I'm not sure what your specific performance concern is -- rendering the View objects, or rendering GL? Nothing you do is going to affect the performance of the GL rendering (except perhaps changing the size of the window).
SurfaceView and GLSurfaceView provide a transparent "place holder" in the View hierarchy that other elements use when computing the layout, but the actual pixels are drawn on a separate layer. This is why the SurfaceView is either behind all View elements or in front of them all -- the layer is passed to the system compositor (SurfaceFlinger), which takes care of generating the final display image.
Related
In my app, for instance, when a user creates a new post, he or she can select a type of media (photo, video, text, place, etc.) and then review it in the following activity.
The way I have been doing it is to have all of the views (i.e. ImageView, VideoView, WebView, etc.) there, but set their visibility to invisible, unless the user chooses that type of media.
For instance, all of the views are invisible until the user takes a photo and then only the ImageView is visible. This seems wasteful though. Before I start the activity, I know which type of media the user chooses, but still have the invisible, unused views.
Would it be smarter to have separate layouts for each type of media with the repeated elements (the create post button, the privacy and venue buttons, etc.)? But this would violate the DRY principle...
How costly are invisible views? What is the correct way of doing this?
Depends on the complexity of the Layouts, I had this issue in previous app, in first iteration I did like you, but in 2nd iteration I found its hard to optimise single layout with bunch of invisible views; much less the if else cases to toggle views visibility.
and about layout performance, also it depends on layout/design complexity, I don't think unused view will consume that much of memory or cpu.
so if your layout is simple, its okay for now, if not I recommend to use separate layout for each design/type.
and as #ashishduh said, the best is to set visibility to GONE instead of INVISIBLE, since the parent layout will not measure GONE views, but this doesn't prevent view usage of memory or cpu (mostly in custom views)
I typically organize my code/logic by a fragment represent one layout. Now I am in need of few relatively simple forms to get input data from user, which are somewhat related in purpose.
Say I hav 3 screens, and I could create 3 fragments to handle them (display view, read input, submit, ..). Or should I use one fragment, and use FrameLayout create a stack of layouts. I was thinking like, stacking all 3 views and hide/display the view I like. But the documentation say
Generally, FrameLayout should be used to hold a single child view,
because it can be difficult to organize child views in a way that's
scalable to different screen sizes without the children overlapping
each other
Any good way to do this or should I create multiple fragments for this (the down side of this is lot of small classes and repeated code. I may use a base class, still like to explore other options)
Thanks.
It sounds like you don't really care that much if the views overlap each other in the FrameLayout, or in fact they are supposed to overlap because you expect to be showing only one at a time. FrameLayout can certainly display stacked child views that each take up its full width and height just fine, and if you set the visibility of the unused views to INVISIBLE or GONE, they will not intercept screen presses or take focus if they happen to be located above the visible view the user is interacting with.
On the point of readability and code maintenance, I think swapping fragments makes more sense though, even if there is more memory overhead. The layout management can be encapsulated within the individual fragments, and you do not need to worry about showing/hiding views, as fragment transactions will take care of that aspect.
What is the purpose of the "view hierarchy" in Android?
as an example:
The SurfaceView exists outside the normal view hierarchy. It actually
exists behind the normal window and is made visible by punching a hole
through the view layout in your app. The SurfaceView can then be
updated independently of the rest of your views without waiting for
the UI thread.
Android's View Hierarchy is the construct (usually a ViewGroup) that contains all of the Views of the active screen in a tree like fashion. Its purpose, Like any other UI manager, is to delegate responsibility of actions and drawing amongst all of the views in a given application.
In your given example, it means that you have created a view that is not part of the application's parent/main ViewGroup and doesn't really have any responsibility, can't do anything useful.
I'm drawing some graphics and i would like to add scroll to it. But with the surface view how to add the scroll programatically ?
SurfaceView is a very special component, it's not easy to mix it with other components. The main reason is due to how it works: when you use a SurfaceView, a new window will be created (by default behind the activity) and all the rendering in the SurfaceView will go to that window. SurfaceView will also "draw a hole" in the activity, so the window behind it will be visible.
SurfaceView needs to synchronize the window position with it's position, which is not done perfectly. For example if you put a SurfaceView inside something which can scroll, the window won't scroll (at least it didn't the last time I tried, around Froyo time).
Please provide some more information about what you are trying to do. If you just want to create a custom component, it's easier to just subclass View and override onDraw(Canvas).
I have numerous activites in my Android app., and most should contain the same, relatively complex set of UI widgets on the screen's top area (lets say that its a kind of toolbar that you can find on most screens).
Right now, every screen's layout contains the markup for this toolbar, along with its logic inside every Activity's source, so it's damn redundant. Could you recommend a more efficient / less redunant way to do this?
I would take advantage of the <include> tag in the layout's xml. This will let you reuse that toolbar very easily and effectively. As for the code I would subclass Activity and place the logic in there, then each of you activities can subclass your custom Activity class.
There are 3 very useful articles on the dev site about this topic. Here is the first one link
I would create a custom View object (subclass View) and then include it in all of your layout xml. You can actually pass parameters, etc. just like built in views. Then define XML for that view that will always be used when that view is drawn on the screen. Also, this allows you to change the view and have that change populated across all of your Activities without having to manually modify all of the code.