I'm looking for a way to document a layout file to improve its reusability.
What I'd like is something that produces javadoc in generated R file like this.
I know it is possible to do so when using <declare-styleable>. This :
<declare-styleable name="myStyleable">
<!-- Some comment -->
<attr name="someAttr" format"color" />
</declare-styleable>
Produces this output i'd like to obtain for layout files without success :
public final class R {
/** Some comment */
public static final int someAttr...
}
Does someone know of the mean to achieve this ? I'm interrested in :
Documenting the layout file, so that documentation be available when using R.layout.my_layout
Documenting a particular element of the file, so that the documentation be available when finding it by id f.e. aView.findViewById(R.id.the_id_that_is_documented)
By the way, I found part of the response : for ids it is possible to add comments if the id is defined in a resource file (in res/values) :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- This is a comment -->
<item name="myId" type="id"></item>
</resources>
Will produce this result in R.class :
public final class R {
public static final class id {
/** This is a comment
*/
public static int myId=0x7f050007;
}
This won't work directly in the layout file if you use #+id/some_cute_id
Edit : and here's the answer for layout files. In fact it might work for everything (Found it browsing sdk sources in res/values/public.xml). This :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
* This layout contains a list that enables to choose a bluetooth device to pair with among paired ones -->
<public type="layout" name="devices_choose" id="0x7f030005" />
</resources>
Produces this output in R :
public final class R {
public static class layout {
/**
* This layout contains a list that enables to choose a bluetooth device to pair with among paired ones
*/
public static final int devices_choose=0x7f030005;
}
}
Related
So I want to make my app name as App5 so I did the following. I went to andriod/app/src/AndriodManifest.xml and edited this file to
android:label="#string/app_name"
And then went to andriod/app/src/res/values/strings.xml and Added my app name as following
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">App<sub><small>5</small></sub></string>
</resources>
But still the subscript isn't working so what did I do wrong
Here your app_name's string is considered to be containing text 'App' and child object sub, that's why it isn't working and you are getting only App instead of App5.
Try instead escaping this <sub><small>5</small></sub> by encapsulating it inside <![CDATA[<sub><small>5</small></sub>]]> so you will have :
<string name="app_name">App<![CDATA[<sub><small>5</small></sub>]]></string>
OR
using html entities and
<string name="app_name">App<sub><small>5</small></sub></string>
(PS : check if your widget accepts and formats html)
UPDATE
I forgot to add < at the beginning and > at the end of ![CDATA[]]
, It has been corrected above
In your activity onCreate method do like this ( using the app_name above)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
//ADD THIS LINE
setTitle(Html.fromHtml( getResources().getString(R.string.app_name)));
...
}
As my title says, how do I include a resource string in XML format that I can access by its id? This id is auto generated in dot42 but I can't find any teachings in Google.
Create a new file strings.xml with this content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="firstName">MisterFive</string>
</resources>
Include it in your project and set the Build Action property to 'ValuesResource'.
If you open R.cs (inside properties folder), you will see that the following code is generated:
//------------------------------------------------------------------------------
// This file is automatically generated by dot42
//------------------------------------------------------------------------------
namespace dot42Application2
{
using System;
public sealed class R
{
public sealed class Strings
{
public const int firstName = 0x7f040000;
}
}
}
You can access your string resource from C# like this:
string firstName = GetString(R.Strings.firstName);
NM! Just figure it out again.
For anyone who came into this problem, just go to:
Solution Explorer > Project(Right Click) > Add > New Item > Dot42 > Android > String table resource > Build (Press F7) > Done!
I am trying to instrument my Android application with some SDK that enables me to test my mobile application on device. I needed to create a MainActivity class in my app where I have the following method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
But I get the following compilation errors:
"activity_main can not be resolved or is not a field"
I have seen postings in this regards and the provided solution has been:
Remove "import android.R;"
Add "import Application.package_name.R;
I have done this as follow:
import com.MyMobileApp.R
Where "com.MyMobileApp" is the package name where R.java resides but the error persists even after a re-build\clean the project.
If I provide the name of the application to import statement is can not be resolved and I do not think its even necessary since I am referencing a package in the same application.
Also, I checked R.java class that is a generated file and seems that can not be modified since Eclipse gives me the warning that the file can not be edited. So in R.java file under layout I do not see any "activity_main" filed in there. I have the following in R.java class under layout:
public static final class layout {
public static final int cycleslistheader=0x7f030000;
public static final int feedback=0x7f030001;
public static final int login=0x7f030002;
public static final int master=0x7f030003;
public static final int overlay=0x7f030004;
public static final int problem=0x7f030005;
public static final int testcycle=0x7f030006;
public static final int testcycles=0x7f030007;
public static final int user=0x7f030008;
public static final int userlistheader=0x7f030009;
So has anyone applied any solution other than the one explained above.
I appreciate your help.
As a simple example of a layout, we will call it activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello_world" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name" />
</LinearLayout>
Go into eclipse, right click on your project -> New -> Android XML file. Name it activity_main.xml and paste the above into it. Save it and you are good to go.
Android dev page for layouts: http://developer.android.com/guide/topics/ui/declaring-layout.html
In your onCreate() method, you are calling setContentView(R.layout.activity_main); This is telling Android that you want the layout for your activity to be the one described in xml in your activity_main.xml layout file (in the layout folder in your res folder). If you don't have one there, it won't be able to inflate the layout and you will get your error. This will give you a very simple view, you can change it as needed for your project. Note there are tons of layouts and views, and you can even make your own custom ones to fit your needs.
I have 2 xmls (they happen to be android text resources), the first one is:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T1">AAAA</string>
</resources>
and the second is
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T2">BBBB</string>
</resources>
I know the attribute of the element that I want to copy, in my example it's TXT_T1. Using python, how to copy it to the other xml and paste it right behind TXT_T2?
lxml is the king of xml parsing. I'm not sure if this is what you are looking for, but you could try something like this
from lxml import etree as et
# select a parser and make it remove whitespace
# to discard xml file formatting
parser = et.XMLParser(remove_blank_text=True)
# get the element tree of both of the files
src_tree = et.parse('src.xml', parser)
dest_tree = et.parse('dest.xml', parser)
# get the root element "resources" as
# we want to add it a new element
dest_root = dest_tree.getroot()
# from anywhere in the source document find the "string" tag
# that has a "name" attribute with the value of "TXT_T1"
src_tag = src_tree.find('//string[#name="TXT_T1"]')
# append the tag
dest_root.append(src_tag)
# overwrite the xml file
et.ElementTree(dest_root).write('dest.xml', pretty_print=True, encoding='utf-8', xml_declaration=True)
This assumes, that the first file is called src.xml and the second dest.xml. This also assumes that the element under which you need to copy the new element is the parent element. If not, you can use the find method to find the parent you need or if you don't know the parent, search for the tag with 'TXT_T2' and use tag.getparent() to get the parent.
This will work only for your simple example:
>>> from xml.dom.minidom import parseString, Document
>>> def merge_xml(dom1, dom2):
node_to_add = None
dom3 = Document()
for node_res in dom1.getElementsByTagName('resources'):
for node_str in node_res.getElementsByTagName('string'):
if 'TXT_T1' == node_str.attributes.values()[0].value:
node_to_add = node_str
break
for node_res in dom2.getElementsByTagName('resources'):
node_str3 = dom3.appendChild(node_res)
for node_str in node_res.getElementsByTagName('string'):
node_str3.appendChild(node_str)
if 'TXT_T2' in node_str.attributes.values()[0].value and node_to_add is not None:
node_str3.appendChild(node_to_add)
return dom3.toxml()
>>> dom2 = parseString('''<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T2">BBBB</string>
</resources>''')
>>> dom1 = parseString('''<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="TXT_T1">AAAA</string>
</resources>''')
>>> print merge_xml(dom1, dom2)
<?xml version="1.0" ?><resources>
<string name="TXT_T2">BBBB</string><string name="TXT_T1">AAAA</string></resources>
I've been working on a Custom Control for Android and although I tried to do what's suggested here there seems to be something I'm doing wrong.
Here's my code to see if anyone can spot the problem:
MyComponent.java
public MyComponent(Context context, AttributeSet attrs)
{
super(context);
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.MyComponent);
CharSequence myId = arr.getString(R.styleable.MyComponent_identifier);
if (myId != null)
{
this.setIdentifier(myId.toString());
}
Integer cds = arr.getInteger(R.styleable.MyComponent_cd_number, 0);
if(cds != null)
{
this.setCds(cds);
}
arr.recycle();
}
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyComponent">
<attr name="cd_number" format="integer" />
<attr name="identifier" format="string" />
</declare-styleable>
</resources>
main.xml
<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bgl="http://schemas.android.com/apk/res/my.test.package.components"
android:id="#+id/table"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<my.test.package.MyComponent
android:id="#+id/hand"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="2"
bgl:cd_number="4"
bgl:identifier="plr"/>
...
</TableLayout>
When I put this I get the following errors:
error: No resource identifier found for attribute 'cd_number' in package 'my.test.package'
error: No resource identifier found for attribute 'identifier' in package 'my.test.package'
If I change my namespace to something like:
xmlns:bgl="http://schemas.mywhatever.com/apk/res/my.test.package"
...the errors go way and the thing runs but myId is null and cds is 0 (the default value!) back on the MyComponent.java constructor.
I'd say it's some very basic mistake but I not being able to spot it and since there's not much documentation on this I decided to ask here.
Thanks in advance!
Ok. I got it solved!
On the original post I had:
xmlns:bgl="http://schemas.android.com/apk/res/my.test.package
...but in my source I had:
xmlns:bgl="http://schemas.android.com/apk/res/my.test.package.components
...because I thought one should put the URI to the components package.
THIS IS WRONG!
On the xmlns it should be the application name as is declared on the Manifest!
When I removed the "components" part of the xmlns it "matched" the application name in the Manifest and the errors went away and when I ran the thing in debug I could actually see the values I was passing to the parameters in the XML!
Hope this helps someone else! :-)
UPDATE
Later on I had the need to move the control into a library and faced the problem again. It seems that when you put the component in a library and use it on a client app you must declare the xmlns as below:
xmlns:myns="http://schemas.android.com/apk/res-auto"
If you do so (and have the library declared as an Android dependency) Eclipse (or is it Android?) will search the dependencies for the appropriate attribute bindings.
I had a problem similar to this, turned out it was calling a different constructor
Try with the constructor that takes in the defStyle parameter
public MyComponent(Context context, AttributeSet attrs, int defStyle)