I am trying to find the original android source code, where the android:text attribute from the layout files is resolved to the actual string referred to via #string/ (for instance: android:text="#string/hello"). The reason is the following: I have created a completely different way of setting up my layouts using a custom XML which in turn uses pre-written Widgets, an example:
<dialog name="Homepage">
<field type="Combobox" label="Enter">
</dialog>
What I want to do: I want to be able to change the label attribute in my example to: label="#string/enter" - so I can make use of the localization feature in android.
But in order to handle those #string commands, I need to know, where this is done in the original Android Source Code (on version 2.3 for instance) so I can imitate the behaviour. So far the only way I know of to obtain string resources is to use context.getString(int resID) - trouble is, how would I go about translating the String "#string/enter" to a res id? I assume I can't, which is why i am curious about how android handles this.
I'd be really grateful if someone could point me in the right direction and I hope my explanation wasn't too confusing :) .
[..] trouble is, how would I go about translating the String "#string/enter" to a res id?
You can use Resources.getIdentifier() for that.
Small sample that gets the res id of #string/enter:
Resources r = getResources();
int resId = r.getIdentifier("enter", "string", getPackageName());
Given that the format for resources is always the same, you can parse all three arguments out of this string and fill them into getIdentifier():
#[<package_name>:]<resource_type>/<resource_name>
from Accessing Resources
Related
I have a pattern that I have been using a lot recently in my apps for as a way to map an Enum value to some resource. So instead of using switches in my code, I can simply ask for "The primary text colour for MyStateEnum.ACTIVE" or some such.
Right now I'm converting the full name of some enum (com.example.app.MyStateEnum.ACTIVE) into a resource name (com_example_app_mystateenum_active) and appending the "name" of the thing I want (primary_text_color) and then running that through getResources().getIdentifier(enumName+"_"+thingName, "color", getPackageName()) to give me the id I need to fetch the resource I want.
However getIdentifier() is slow compared to using R.color.com_example_app_mystateenum_active_primary_text_color so I'd like to find a better way.
I think that better way is to generate code in the exact same way R is generated so that I can more easily access the the ids. I'm thinking that something like this will work:
colors.xml:
<color name="some_name"
ex:use="primary_text_color"
ex:value="com.example.app.MyStateEnum.ACTIVE">#FF00FF</color>
<color name="some_name_default"
ex:use="primary_text_color">#FF0000</color>
something.java
int activeColor = getResources().getColor(X.color.primary_text_color.getForEnum(MyStateEnum.ACTIVE)); //#FF00FF
int activeColor = getResources().getColor(X.color.primary_text_color.getForEnum(MyStateEnum.INACTIVE)); //#FF0000
(I hate picking names, but you get the idea). I would like to have those values automatically updated like R is as well.
My problem is that I'm having a hard time finding anything suggesting where I should start. I'm not sure if its a matter of "you're asking the wrong question" or "no one has wanted to do this before so start reading the source code for the android plugin".
I have read in many places that you should declare your String objects in your resource file but I haven't read about any benefits anywhere.
I have already declared all my Strings that I have in my layouts as resources but I haven't done so in my classes.
My question is:
What are the benefits of declaring Strings as a resource? Are there any memory benefits?
Internationalisation,
Keeping all of your strings in a single place (where they can be editted globally),
Changing strings based on device (mdpi/large/portrait)... I mean, it'd be really rare for this
last one, but it's possible.
Sharing the same string among many layouts (this will happen in any app which isn't tiny)
The top one I reckon is: Translations! Put a new strings.xml in the right folder and the app translates itself for each device.
But there's a matter of organisation too. Just like the layout, you normally don't build in the code, because that's not the place for it.
The code is to process stuff. The string is just one more of the resources that your code will use to show stuff on the screen.
One of the main benefits is for localization: you keep your code language-independent and just need to provide a different XML file for each language you want to support.
Suppose I have an Activity, for which I set the content view from a XML file.
Let's say I have a button, acceptButton, in the Java code.
acceptButton =(Button)findViewById(R.id.acceptBtn);
In the above code, the Java name and the XML id are different. Is there a "best practice" or standard for naming widgets? For example, should the XML id be called acceptButton too, instead of acceptBtn? It seems trivial, but it annoys me what other people do, when they give the Android name and XML id completely different names.
There is no recommendation from Google about naming resources in xml files. Also checking Code Style Guidelines for Contributors you find no mention about it, so the best would be taking a look in the SDK where you can see Google is not consistent in identifier naming.
Across the SDK you can find conventions as follow:
mHeaderText = (TextView) view.findViewById(R.id.headerText);
mHeaderText = (TextView) view.findViewById(R.id.header_text);
mHeaderText = (TextView) view.findViewById(R.id.HeaderText);
What I recommend is to be consistent per project. Decide for one naming convention and use it across the entire project.
It is never mandatory that Java name and XML id should be same. And I don't think that there are any such naming standards provided by Google. But it is seems very good practice if both of them are same. By keeping them same, we can easily identify the control by name only when there are more than one controls.
Other way is you can define a naming style of java name and XML id and follow same for all the controls. But it is developer or project specific.
It is never mandatory as Nirav said but having same name for id and Variable is good practice i always do this. This thing saves your time you don't need to remember different name for Id in xml and variable in code and also you just copy and paste after defining it in xml to code.
I would interpret it more colsely to Java conventions: "AcceptBtn" to point a class, "acceptBtn" to point an instance, "accept_btn" - others. "id" is more like an instance, definetely not a class. At least others. But I would prefer it as an instance.
R.id.AcceptBtn // As a class.
R.id.acceptBtn // As an instance.
R.id.accept_btn // Other cases.
Also as per Steve McConnel's "Code Complete" acceptBtn is more preferable to be written as acceptButton. It is more readable and less writable, but we read code more often than write it. So readable code saves more time.
I am not sure if anyone was bugged with this issue before, but it is one big pain for me.
How do you give an id to xml element in android?
Right now, I set the id with the pattern [activity/fragment name][element type][specific name]. For example, if I had an EditText to keep an email which is used in LoginActivity, I will give the id 'LoginEditTextEmail'.
The problem I'm facing is, with this approach, the id often ends up in a very long one.
How do you set the id? What is the best practice?
Descriptive names are ideal (same as with the name to any variable in any programming language).
I think you have a good system already I would offer these potential ways to decrease the size of your IDs
[activity/fragment name] - Personally I would drop this, I tend to use one layout file per activity / fragment anyhow so there is no confusing what activity the view is meant to be in. Also there are times when I re-use some View widgets in multiple activities and I will leave them with the same ID so that the code to find and interact them is simplified (i.e. it can be copy/paste or put into a subclass of Activity)
[element type] - I use a 3 letter shorthand for the widget types:
Edt = EditText
Txt = TextView
Lbl = TextView that is static for labeling something
Btn = Button
Prg = ProgressBar
Lyt = Layout
etc...
[specific name] - no real improvement to be made here, it has to be as long as it has to be to describe what it is for.
You're overcomplicating things. Just name it in whatever way is memorable to you. IDs only have to be unique per XML (i.e. you can have 50 different layouts with the id of my_edittext) since you find a view by it's ID only through a single view hierarchy.
Much like naming anything, I tend to use the shortest name possible that accurately describes it. In the case of ids for layouts, just make sure each id is unique in your layout (you can reuse the same id in a different layout).
Drop fragment, activity and type unless you qualify these in coding, so:
boolean isLoggedIn = false;
android:id="#+id/is_logged_in"
As mentioned in other responses the XML provides the qualifier, now you have to decide whether consistency and/or further qualification is necessary and if it befits. Do you really need to qualify and if you don't is supporting the code going to be a lot harder by you or anyone else?
So what about strings.xml?
prefix the id with a frag or activity qualifier. So, for example:
<string name="profile_is_logged_in_true">Logged in.</string>
<string name="profile_is_logged_in_false">Not logged in.%</string>
Also…
<plurals name="plural_is_logged_in_duration">...
I've toyed with:
<string name="profile_isloggedin_false">Not logged in.</string>
But not yet convinced. This is actually a classification problem, now since solved in other disciplines by tagging. Java provides dotted namespace and type qualifiers, so
com.example.android.app.profile.State.isLoggedIn
Android uses things like R.string :-) So you have the Java plus some additional namespace from Android. Don't forget you can have more than one string resources file, so perhaps:
res/values/widget_defaults.xml
could contain some default values for say a TextView. The true and false strings should be handled by plurals - but the example hopefully helps, despite a tad contrived.
In normal, we should use #+id/ to define an id and use #id to reference an id. Today I found #+android:id/title in apps/settings/res/layout/preferenc_progress.xml.
How to understand it and how to use it?
It is used for resources that are shipped with the SDK.
You can take a look at them by browsing to
[PATH TO ANDROID SDK]/platforms/android-[VERSION]/data/res
By using the android in android.R.whatever you just specify the R file to look up. For more information you should read Accessing Platform Resources.
That belongs to the app preferences activity screen definition.
title and summary are standard Android fields of a TextView preference item.
I think it does the same thing. It's just a more formal way of saying it by specifying where the namespace is.
I've never met this way of giving id, but in theory this means adding new id title to android package. So you'll be able to use it in your code like android.R.id.title. But I'm not sure resource compiler will really create any id in android package. I think it can be used only with predefined ids. But I'll give you more precise answer later, when I'll be able to check it.
EDIT: I've checked it and found some differences. Firstly, if you define Android's id using #+android:id/some_id, which is already present in SDK, this id will not be defined in your R.java file. If it's not present in SDK, it will be defined in R.java, but with different kind of value. Secondly, if you'll try to convert id from its string representation to int value, Resources.getIdentifier() method will return 0 in case of #+android:id format.
This means it will create an id in your resource file.