Difficult to try and phrase this question, but I will try my best.
Basically, I have an application and I would like to split the code up more. To try and explain this, will give an example of one of my screens.
In my home screen, I have a title, user details, balance, next bill details and usage details. I want to split each of these sections into their own views. So what I have in my main XML file is I have 5 different RelativeLayouts, like this
<RelativeLayout android:orientation="vertical"
android:layout_below="#+id/title" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:id="#+id/layout1">
</RelativeLayout>
One for each function I want to have on my home screen. And as you can see I also have each layout set below the previous layout, so the order is title, layout1, layout2, layout3, layout4. (The reason I am doing this is, that I want each layout to be interchangable, i.e. I could remove layout2, and order then be title, layout1,layout3,layout4 as I may not need the 2nd layout depending on what is required of the app)
So in my main activity class, I have called each of these layouts.
layoutTitle = (RelativeLayout) findViewById(R.id.title);
layout1 = (RelativeLayout) findViewById(R.id.layout1);
layout2 = (RelativeLayout) findViewById(R.id.layout2);
layout3 = (RelativeLayout) findViewById(R.id.layout3);
layout4 = (RelativeLayout) findViewById(R.id.layout4);
Then I use layout inflator like so
View view;
LayoutInflater inflater = (LayoutInflater) getBaseContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.userdata, null);
to set up the layout for each layout I have defined in my xml file.
What I want to know is, is it possible to inflate another activity rather than an XML file? The reason I ask this is, that each function I said the home screen is made up of, title, user details, balance etc, I have an activity for each of these. Each of these functions has custom functionality that I have designed, such as animation etc. If I simply inflate these xml files, then I can't access the widgets inside so I can't set up the functionality from Java which is what I need.
If I was able to inflate another activity, then this would not be a problem, as I would set up the functionality for each function in activity, then just inflate that class.
I hope my question was clear, if not I can expand on any areas you are not sure about.
Would be very grateful for any assistance!!
EDIT: If it is not possible to inflate a class, then is there any other way method you could recommend that could solve my problem?
I do exactly the same as you.
I use composition in my Java activities to achieve the sharing of functionalities across my activities. I think of activities as "context", and not as parts of my page that get replicated. So when I am in a certain context (an activity), I then display layout1, layout2 and layout3 with specific parameters, and specific contents that depends on that activity. On another activity, layout1, 2 or 3 could be different, but they have the same location on my screen all the time.
I use composition through views: all my activities have a superclass (call it anything you want, something like ActivityWithCustomLayout, which contains all my layout as class members (as ViewGroup). They are protected, so each of the variables layout1, layout2 and layout3 are available to all subclass activities of this superclass.
And when on a specific activity, I populate each of the layouts on my onCreate method with:
layout1.addView(...something inflated from an XML that depends on that specific activity...);
layout2.addView(...same principle...);
So in fact all my XML layouts are "parts" of activities, which I inflate at runtime into views, that I add dynamically to my activity when needed.
You're right, these explanations are not easy :)
If you target Android >= Honeycomb (including ICS) then have a look at the Fragment framework, it may be a simpler way to achieve all of that (haven't had a look at that yet).
Not too much of an answer but I often find myself subclassing the layouts themselves. Then, in the onFinishInlate() callback, I wire up all of my view references using findByViewId. In your XML, you can replace <RelativeLayout> with <com.company.CustomLayout>, assuming that your CustomLayout is a subclass of RelativeLayout.
As mentioned, you can then pull them out into separate files and include them with the include tag. This makes refactoring easy and allows you to reuse the layout components.
Or, if you inflate these subclassed layouts from within your code, you don't have to worry about all the messy findViewById calls in your activity.
Fragments are also great and have similar life cycles to an activity. Good luck!
I'm not sure that you need to inflate all of those Views from within your Activity. Look into using the include and merge tags within your Layout. This should help get you started: http://developer.android.com/resources/articles/layout-tricks-merge.html
You can also toggle the visibility of your Layouts. So, you can declare them in XML, initialize them as visibility="false", and then toggle that visibility in your Java code.
You also stated: "If I simply inflate these xml files, then I can't access the widgets inside so I can't set up the functionality from Java which is what I need."
You can access any Layout component after it has been added to your Activity using findViewById and casting the object it returns to the appropriate type.
Related
ViewSwitcher can be used only for two childs in it. But for a group of textviews to be converted to Edittexts what can be the ways?
It's easy enough to replace views for other views but converting - I don't think so.
To replace views, you can simply do something like the following:
LayoutInflater inflater = LayoutInflater.from(this);
View view = inflater.inflate(R.layout.edit_texts_layout, null);
viewSwitcher.removeAllViews();
viewSwitcher.addView(view.findViewById(R.id.first_edit_text));
viewSwitcher.addView(view.findViewById(R.id.second_edit_text));
So what's going on here?
1) You create a layout called edit_texts_layout which contains two EditText's with the ID's: first_edit_text and second_edit_text.
2) You then inflate this in your Activity or Fragment.
3) You then remove all of the existing views in your ViewSwitcher since, as you rightfully said, there can only ever be two views in a ViewSwitcher.
4) You then add the two EditText's inside that ViewSwitcher by view.findViewById()
Also...
It would be wise to have another layout called text_views_layout and do the exact same thing so that you can switch the EditText's with the TextView's.
But why have the EditText's inside a layout and not create them programmatically?
Good question. Views should live in layouts and live separately from code when possible. It makes life easy where you can work with a view in a layout since you have XML autocomplete and the preview screen so you know exactly what the view looks like - saving you from any nasty surprises later on.
Are there any other alternatives to this?
There's always more than one way to skin a cat and this situation is no different. You could possibly create TWO ViewSwitcher's and with different child views. What you'd have to do then is toggle the visibility to View.GONE and View.VISIBLE alternatively. The caveat? It'll be troublesome to maintain both in memory and to perform any operations on the child views as you'd have to remember which one is visible and which one isn't. With my original answer, you won't have to worry.
Let's say i have the Android XML file home_page.xml.
on this home_page.xml i have some variations that i want to show at different activities, and i'd like to reuse the same main layout home_page.xml.
For example, imagine variations on the page such as:
there's 2 more buttons if the user is in state A
there's 1 more editText field if the user is in state B (same activity as state A)
there's a different arrangement of layout on the Z-axis in a frame layout if the user is in state C (same activity as state A)
i know it's possible to programmatically say hide views and set views as visible. but is there a better way to do this via xml or something?
Android recommends using 2 Tags for re-using the layouts across different screens.
Include
When to Use ?
If you already know the layout that you want to re-use, create a new XML file and define the layout. Use tag to re-use it.
Merge
When to Use ?
To eliminate redundant view groups in your view hierarchy when including one layout within another, we can use tag.
Refer to this link - http://developer.android.com/training/improving-layouts/reusing-layouts.html for code sample and more details.
You can hide views but using the Visibility flag.
View v = findViewById(R.Id.my_view);
v.setVisiblity(View.GONE); //etc.
I've tried stuff like this before. I had mixed results. This is fine if you are doing things, like asking the user for a name, then showing an address input or something. But if you find yourself with like 3 or 4 conditions for one editText and then different ones for a button in the same class you might want to just use different layouts. A lot easier to manage.
The app I am working on requires a dynamic layout that displays a HorizontalScrollView of profiles. A profile is simply a RelativeLayout with a picture and some text. Since I get the data from a data file, I need to create a Relative layout for each of profiles. At first I created each RelativeLayout programmatically in a for loop and then added it to the parent view. This works, but I don't want to do it this way. I want to use different layout files based on the screen size of the device, etc.
Then I thought. Well, what if I had a Layout with just one profile on it? My code could get that one profile with findViewById() and then create new ones based off of it! In other words:
// get the layout
profileLayout = (LinearLayout) findViewById(R.id.profileLayout);
// get the first profile in the layout
originalProfile = (RelativeLayout) findViewById(R.id.profile1);
// make copy of profile
temporaryProfile = originalProfile;
// make changes to the this profile and add it back
profileLayout.addView(temporaryProfile);
Of course, this doesn't work because this is java and temporaryProfile is now a reference to originalProfile. So is there any way to make a copy of this RelativeLayout? I'm aware of LayoutInflater, but I still don't understand how it works. There is also Object.clone().
Not so much. Sounds like your particular case could benefit from a ListView of some kind and an adapter (see resources like this for info). If not, then a LayoutInflater is the best answer as it does precisely what you want. Acquiring one you can then use it to "inflate" any view you've defined in your XML layout files and do whatever you want with it.
Here's a great discussion of the inflater.
you can make a copy of your inflator with a new context. Layout Inflater - Android Developers
Why not simply use an include in the xml file for the layout that you want.
I want to create a pocket reference application. So, much of the content would be texts, linkbuttons and images.
I wonder where is a good place to put all of the contents. I could place it hard-coded on the source code, So, when a user click a linkbutton, a new view will be opened and in the source code I specify the TextView and setText, etc. But I think it's not a good idea. Can I put the content in an xml file or in a database? Which one is better for this case?
I see that we are encouraged to put layout in main.xml. But, from what I read, the xml layout is static, what if I want to put some TextView, but I don't know how many TextView would be displayed, because the content would be loaded dynamically/programmatically?
Thank you.
Not sure it this is what you meant:
You can initialize your application ui by an android xml file layout.
to inflate, you use this method.
in your activity's onCreate()-Method or even later, you can then get the TextViews or whatever you want by calling findViewById(R.id.textview). Note that this method will search all over the layout xml file for the specified id and though blocks the ui thread while searching. if your textview is very near at bottom and many other elements come before it, this can take some time.
if you want to build your own layout dynamically, you have to do this programmatically of course.
for general layout declaring, refer this tutorial on android dev guide.
You could write the textView in a xml layout and inflate it dynamically in the activity as many times you want
View view = getLayoutInflater().inflate(R.layout.scroll_project, null);
//then add the view in linear layout as
layout.add(view);
I'm reading the book 'Hello, Android'. In the Sudoku example, it uses a options menu. It needs a MenuInflater that we use to read the menu definition from XML and turns it into a real view.
To use button, textview, or many other views, I don't need to inflate them.
My question is, in what situations, I need inflaters? Why doesn't Android treat menus like other views?
You need an inflater at every place that you want to dynamically create a view out of an XML file.
Activity layouts are automatically inflated when you call setContentView() as they're always required.
But when the menu is required — which is only when the user first presses the Menu button — the XML-defined layout needs to be manually inflated.
Similarly, if you have a ListView, you don't know in advance what rows will exist, so we have to inflate a View from XML for each row in the list, as they're required.
Inflaters are mainly used for parsing Xml layout into view objects. As mentioned above the inflation is needed for making a link between the UI defined in the Xml for manipulating and making developer.
Whenever UI Updation is needed we need inflation and UI Updation is done through view object and developer can dynamically create view and add to existing view.
Hence inflation helps developer to change behaviour of UI in xml layout according to specified condition in a program.
With inflation, we are able define controllers in MVC for each xml layout where xml is view.
Menu is also a view it has to inflated In certain code such setContentView(specifiedLayout) includes inflation
But in earlier version it was not like this it was like setContextView(getInflater().inflate(specifiedLayout))
for ease of programming,android developers have incorporated inflation in setContentview() and there are lot scenarios like add view to layout addView(),etc..In most cases inflation has incorporated in code that why most of beginner does know inflation concept and has difficulties in understanding inflation in android.