I'm new to Android and find it brutal (there seems to be an near infinite number of details and dependencies to remember).
Anywho, I got the TextSwitcher1 example app working, which uses ViewSwitcher. I'm assuming ViewSwitcher is the way to go, need to either display a map or a table, user can pick, and switch back and forth.
So I created my MapActivity in another application, seems to work. Next integrate into main app. So, call
View v = findViewById(R.layout.mapview);
and then
mSwitcher.addView(v);
except "v" is null. Why? Do I create the activity? But I don't want to show it yet. Is there such a call as "create activity but hide it until needed"? Or am I barking up the wrong tree?
Thanks for any insight.
The findViewById function returns a View based on an ID resource (R.id.something) for whatever view you have loaded in your activity (using setContentView(R.layout.main)). In your sample code, you're using a layout resource (R.layout.mapview). You should inflate the XML file, which will return a View that you can use to add to the ViewSwitcher.
Example Code:
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.mapview, null);
mSwitcher.addView(v);
However, you should be able to define everything in your XML file and not have to manually add the pages to your ViewSwitcher. Here's some example code on how to do that: http://inphamousdevelopment.wordpress.com/2010/10/11/using-a-viewswitcher-in-your-android-xml-layouts/
Related
TL;DR: Is there anything in com.android.layoutlib.bridge.android.BridgeContext that can substitute for Activity#findViewById(...)? I've looked at the source, but I can't find anything.
When running on a real device, an attached view's #getContext() returns the Activity. The view can cast it and call #findViewById(...) to obtain a reference to some other view.
But when running in a WYSIWYG editor, #getContext() returns an instance of a different class. I'm getting com.android.layoutlib.bridge.android.BridgeContext. This class isn't part of the public API, so I'm planning to access it via reflection and degrade gracefully if the implementation changes.
If you're wondering why my view wants a reference to another view... I've created a view that appears to have a hole in it. It works by delegating its drawing to another view. If the view with the hole is placed on top of other views, then it appears to punch a hole through any views beneath it, all the way down to the view it's using for drawing. It works perfectly on a real device, but it would be nice to have it also work in the WYSIWYG editor.
It's bad to assume that View.getContext(), or any other platform method that returns Context, can be cast directly to more concrete classes, like Activity. There exist classes like ContextThemeWrapper which can easily destroy your assumption.
I would recommend restructuring what you are doing so that you have a parent layout that can act as an intermediary for the hole-y View and what's below it.
Or you could have a setter which would provide the View for you.
A last option is to call View.getParent() a bunch of times to get the root View and call findViewById() on that:
ViewParent parent;
while(getParent() != null) {
parent = getParent();
}
View root = (View) parent;
root.findViewById(R.id.my_view);
BTW, BridgeContext is used in the WYSIWYG in place of Activity because it only mocks the Android View/Layout/Rendering system, it doesn't emulate it completely. This can be seen in other ways like how it renders shadows or shape drawable rounded corners.
I awarded the bounty to dandc87 because his answer led me to the solution. However, the code snippet in his answer crashes with a ClassCastException because the root ViewParent is not a View. The mods keep rejecting my edits, so here's the complete and correct solution:
private View findPeerById(int resId) {
View root = this;
while(root.getParent() instanceof View) {
root = (View) root.getParent();
}
return root.findViewById(resId);
}
I used to do alot of Flash Actionscript and now I am getting into Android. Is there something in the Android API that is similar to duplicateMovieClip() in Actionscript? I'm sure there is probably a way to write such a method, but I am wondering if there are any existing shortcuts.
For example, say I have an ImageView, TextView, or other kind of View Object on screen and I want to have a button to click which will make a duplicate of some object on screen.
If you don't mind my asking, why do you need something like duplicateMovieClip()?
To answer the question, Android doesn't have a notion of the AS2 duplicateMovieClip(). Much like in AS3 (which also didn't have duplicateMovieClip()) you'll have to implement your own cloning method. Java does have an unimplemented '.clone()' method as part of every Java object, so if there's a particular View you would like to clone you might be able to implement your cloning there by
Overriding the clone method.
I think what you'd probably end up doing instead is doing something more akin to instantiating from the Library by making small view layouts in xml and inflating them using the Inflater tools.
View result = null;
// where pContext is a context object, either supplied by the application
// or just by the current Activity (if available)
LayoutInflater inflater = (LayoutInflater) pContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// where id is the layout id such as R.layout.myclonableview.
// where pRoot is the parent container for the new result.
// where pAttachToRoot is whether to immediately inflate the new view into the root.
result = inflater.inflate(id, pRoot, pAttachToRoot);
// Now "clone" your old view by copying relevant fields from the old one to the
// one stored in result
In my application I have 2 layouts. One's is root layout that changes dynamically and the second is just a form that opens many times. The form must be child of the root layout but I'm failing to perform so.
I assume that I should simply use:
main.AddView(formLayout)
but I can't figure out how get this formLayout object.
Will thank you for possible answers.
Sounds like you need the LayoutInflater object Android reference.
This allows you to create an object from the xml layout in your project.
With the advice of cjk I wrote piece of code that actually answers my question:
setContentView(R.layout.main);
main = ((ViewGroup)findViewById(android.R.id.content));
LayoutInflater inflater = this.getLayoutInflater();
ViewGroup form= (ViewGroup) inflater.inflate(R.layout.formLayout, null);
main.addView(form);
Thank you all
Not sure if I understand the question properly, but something like that might work:
View myView;
myView = (View) this.findViewById(R.id.formLayout);
main.addView(myView);
By get I figure you mean you want to retrieve a field in the new opened layout, you can do it by making it a new Intent and using startActivityForResult instead of startActivity.
TextView txtOtherMatches = (TextView) dialog.findViewById(R.id.txtOtherMatches);
txtOtherMatches.setText("Other Matches");
i m getting this error while running application and i m just assigning simple text to Textview at run time .....
java.lang.NullPointerException
Make sure your TextView in the xml has exactly the same id: android:id="#+id/txtOtherMatches"
Check that you don't have more than one res/layout folder (e.g., layout-normal, layout-large or layout-land) and, if you do, make sure that your TextView is present in the layourt corresponding to your device/emulator
Check that it was added to the current View (most probably, through some ViewGroup)
If everything else fails, clean the Eclipse project and rebuild
txtOtherMatches is probably null because it doesn't exist in the current view.When you use findViewById the view must be in the "contentview" you've set with setContentView, or added later tot the view. You can't find any "random" view that has an ID somewhere, it must actually be "present" in your current view.
If the view is NOT in the xml you're using already, but somewhere else in one of your xmls, you must use an inflater to get the View, and add it with View.add()
It would be helpfull if you provide a few more lines before that one.
But my guess is Nanne is right.
Try to add a safety check:
(this wouldn't change the code flow)
if(txtOtherMatches == null) {
throw new NullPointerException("darn, the R.id.txtOtherMatches is not in the dialog")
}
(on the other hand Nanne mistakenly mentions 'current view' while I'm sure he meant the 'dialog' view.
Put some more meat if you need further assistance ;)
This is a dumb question and I know the answer is sitting in front of me, I'm just having trouble searching for it in the right way.
I've got a custom view that has been set as the content view and inflated from xml. How can I access the instance to call methods on it from the activity class? I remember seeing something akin to getResourceById() a while back, but now I can't seem to find it and I'm not even sure if that's the best way to do it.
Sorry for the dumb question.
If you have used an inflater, you will be given an instance of a View class. You then use your instance like so
LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = li.inflate(R.layout.small_listview_row, null);
TextView tvItemText = (TextView)row.findViewById(R.id.tvItemText);