I've got a question on custom view XML-declarations.
I created my own View with the custom attributes as normal. Now I want to add more complex attributes like this: (This is non-working code)
<com.xxx.yyy.CustomTextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/customTextView1"
android:layout_marginBottom="22dp"
android:layout_toRightOf="#+id/buttonBlack"
android:text="TextView" >
<Animation
animation:property1="123"
animation:property2="456" />
<Animation
animation:property1="789"
animation:property2="012" >
</Animation>
</com.xxx.yyy.CustomTextView>
I didnt find a way to do this on my own but maybe someone has got an idea.
Thanks!
Edit:
I just solved the problem more or less nicely.
I created a new .xml file in my /res/xml folder called animations.xml
<animations>
<animation
name="Animation name 1"
float1="1.1"
float2="1.2"
integer1="11"
integer2="12" />
<animation
name="Animation name 2"
float1="2.1"
float2="2.2"
integer1="21"
integer2="22" />
</animations>
My custom view in attrs.xml contains an attribute which is used to reference the animations.xml file from above:
<declare-styleable name="MyTextView">
<attr name="animations" format="reference" />
</declare-styleable>
Now i parse the referenced .xml file in the constructor of the MyTextView as described here: http://thedevelopersinfo.com/2009/12/14/using-xml-file-resources-in-android/
Maybe this helps somebody at some time.
Unless CustomTextView extends ViewGroup (or has it in it's class hierarchy) and Animation is a custom view you've defined, this will not work. Only Views and ViewGroups are allowed in layout XML files (and some special tags defined by Android like include and merge), and only ViewGroup elements can have child elements.
You can add custom XML attributes to your custom view like this:
<resources>
<declare-styleable name="YourCustomClass">
<attr name="someCustomAnimationAttribute" format="reference" />
</declare-styleable>
<resources>
How you obtain it is described here:
http://developer.android.com/training/custom-views/create-view.html#applyattr
In your layout you have to declare a namespace:
xmlns:app="http://schemas.android.com/apk/res-auto"
and then use it like this:
<com.xxx.yyy.CustomTextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/customTextView1"
android:layout_marginBottom="22dp"
android:layout_toRightOf="#+id/buttonBlack"
android:text="TextView"
app:someCustomAnimationAttribute="#drawable/someAnimation">
That way you can supply those animations via XML instead of adding them as as child elements which is not possible.
Related
We want to create an Android Class Library to reuse some code, mainly custom views.
I have successfully created and referenced the views in Xamarin.Android projects.
The only issue I've got is I cannot use the declare-styleable. The view is looking fine, but can't use custom attributes in the XML layout.
<resources>
<declare-styleable name="MyCustomView">
<attr name="srcLittle" format="reference" />
</declare-styleable>
</resources>
And this is how I use it:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/res-auto"
[...] >
[...]
<Core.MyCustomView
android:id="#+id/item_proposal_validation_trips_icon"
android:layout_gravity="center"
android:layout_height="48dp"
android:layout_width="48dp"
app:srcLittle="#drawable/ic_plane" /> <-- ERROR
[...]
</android.support.v7.widget.CardView>
Error in XML:
The "http://schemas.android.com/apk/res/res-auto:srcLittle" attribute is not declared
Error compiling:
1: error: No resource identifier found for attribute 'srcLittle' in package 'res-auto'
Thanks.
The namespace you've defined for the app prefix in your layout is incorrect.
xmlns:app="http://schemas.android.com/apk/res/res-auto"
The correct namespace for your app-defined attributes is http://schemas.android.com/apk/res-auto. You've got an extra res/ in there. It should be:
xmlns:app="http://schemas.android.com/apk/res-auto"
Update: There were 2 custom attributes defined in CustomTextView.. If both are defined in xml it works fine.. If first is missing it does not give any value for 2nd also...
<com.mycompany.projectname.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:extraColor="?someColor"
/>
Here someColor is another color attr which varies for different themes..
I need value of extraColor custom attribute in MyCustomView class...
Currently obtaining it as below:
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView, defStyleAttr, 0);
a.getColorStateList() does not work here...
CustomTextView defined as:
<declare-styleable name="CustomTextView">
<attr name="state" format="boolean" />
<attr name="extraColor" format="reference|color" />
</declare-styleable>
Update: There were 2 custom attributes defined in CustomTextView..
If both are defined in xml it works fine.. If first is missing it does not give any value for 2nd also...
Could you try that one..
a.getColor(R.styleable.CustomTextView_extraColor, Color.WHITE)
use only either reference or color
<declare-styleable name="CustomTextView">
<attr name="extraColor" format="reference" />
</declare-styleable>
And then if it is reference get it like,
a. getColorStateList(R.styleable.CustomTextView_extraColor);
if it is color then,
a. getColor(R.styleable.CustomTextView_extraColor, Color.WHITE);
In addition to what others have said, it looks like the naming is inconsistent (copy+paste error?): in most of the code you posted, your refer to a CustomTextView, but in the XML, you use MyCustomView.
Try changing your XML:
<com.mycompany.projectname.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:extraColor="?someColor"
/>
What is the difference and more importantly the necessity of having different prefixes in Andriod view XML?
For example,
<android.support.v7.widget.Toolbar
android:id="#+id/actionToolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentInsetEnd="20dp"
app:contentInsetEnd="20dp"
android:elevation="3dp"
/>
Has contentInsetEnd for both android and app.
android is usually used for attribute coming from Android SDK itself.
app is often used if you are using the support library.
You may also see other namespaces if you are using custom views (of your own or form a library).
Here is some extra information: http://developer.android.com/training/custom-views/create-view.html#customattr
app namespace is used for custom defined attributes, which are usually defined in /values/attrs.xml Here is a sample of such file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SimpleTabIndicator">
<attr name="numberOfTabs" format="integer"/>
<attr name="indicatorColor" format="color"/>
</declare-styleable>
</resources>
And a sample usage would be
<com.someapp.demo.SimpleTabIndicator
android:id="#+id/tabIndicator"
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="#26292E"
app:indicatorColor="#FFFDE992"
app:numberOfTabs="5"/>
Android namespace you use for Android's widgets and UI controls.
app is just a namespace for any custom parameters for a custom View.
This can be anything but if you see the root element there's probably a line xmlns:app="http://schemas.android.com/apk/res-auto" that assigns the namespace .
I have a class extending LinearLayout which receives an array and creates a layout based on
the array.
Now creating the layout in the OnCreate method of the activity and using setContentView
to the layout.
I want to know whether I could use it in an XML as I would use LinearLayout or a similiar way in a layout xml file.
If you want to use your custom LinearLayout in your layout, declare a new element with <path_to_your_custom_layout_class....
Yes you can.
in XML layout:
<com.my.package.MyView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:MyStyleable="http://schemas.android.com/apk/res/com.my.package"
android:id="#id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
MyStyleable:attr1="ATTR1 VALUE"
MyStyleable:attr2="ATTR2 VALUE" />
Notice the custom xml namespace xmlns:MyStyleable which will contain the custom attributes.
Define the custom attributes in res/values/attr.xml :
<resources>
<attr name="attr1" format="string" />
<attr name="attr2" format="boolean" />
</resources>
Then in your custom view class, retrieve the values from XML :
String attr1 = a.getString(R.styleable.attr1);
boolean attr2 = a.getBoolean(R.styleable.attr2);
Hope it's clear. !
I would like to create an custom View on Android. I have tried to do it as simple as possible and created an almost empty class MyView and used it in my LinearLayout but the application fails on start with "Force Close". How can I do a simple custom View? According to Building Custom Components the View gets the size 100x100 if I don't override onMeasure().
public class MyView extends View {
public MyView(Context context) {
super(context);
}
}
And I use it in a LinearLayout with:
<view
class="com.example.MyView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.0" />
What am I doing wrong?
If I use the constructor that itemon suggest and the corresponding call to the superclass. Then the "Force Close" is gone, but my LinearLayout is broken, the components after MyView isn't shown.
Here is my 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:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.0"
android:background="#f00"
android:text="Hello"
/>
<view
class="com.example.MyView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.0"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.0"
android:background="#00f"
android:text="World"
/>
</LinearLayout>
may be you could define another constructor method like this:
public MyView(Context context, AttributeSet attrs)
the android framework will try to build the UI with your view from the constructor above.
The Android Developer Guide has a section called Building Custom Components. Unfortunately, the discussion of XML attributes only covers declaring the control inside the layout file and not actually handling the values inside the class initialisation. The steps are as follows:
Declare attributes in values\attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
<attr name="android:text"/>
<attr name="android:textColor"/>
<attr name="extraInformation" format="string" />
</declare-styleable>
</resources>
Notice the use of an unqualified name in the declare-styleable tag. Non-standard android attributes like extraInformation need to have their type declared. Tags declared in the superclass will be available in subclasses without having to be redeclared.
Create constructors
Since there are two constructors that use an AttributeSet for initialisation, it is convenient to create a separate initialisation method for the constructors to call.
private void init(AttributeSet attrs){
TypedArray a=getContext().obtainStyledAttributes(attrs,R.styleable.MyCustomView);
//Use a
Log.i("test",a.getString(R.styleable.MyCustomView_android_text));
Log.i("test",""+a.getColor(R.styleable.MyCustomView_android_textColor, Color.BLACK));
Log.i("test",a.getString(R.styleable.MyCustomView_android_extraInformation));
//Don't forget this
a.recycle();
}
R.styleable.MyCustomView is an autogenerated int[] resource where each element is the ID of an attribute. Attributes are generated for each property in the XML by appending the attribute name to the element name. Attributes can then be retrieved from the TypedArray using various get functions. If the attribute is not defined in the XML, then null is returned. Except, of course, if the return type is a primitive, in which case the second argument is returned.
If you don't want to retrieve all of the attributes, it is possible to create this array manually.The ID for standard android attributes are included in android.R.attr, while attributes for this project are in R.attr.
int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};
Please note that you should not use anything in android.R.styleable, as per this thread it may change in the future. It is still in the documentation as being to view all these constants in the one place is useful.
Use it in a layout files such as layout\main.xml
Include the namespace declaration
xmlns:app="http://schemas.android.com/apk/res/com.mycompany.projectname"
in the top level xml element.
<com.mycompany.projectname.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:text="Test text"
android:textColor="#FFFFFF"
app:extraInformation="My extra information";
/>
Reference the custom view using the fully qualified name.
Android LabelView Sample
If you want a complete example, look at the android label view sample.
LabelView.java
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);
attrs.xml
<declare-styleable name="LabelView">
<attr name="text"format="string"/>
<attr name="textColor"format="color"/>
<attr name="textSize"format="dimension"/>
</declare-styleable>
custom_view_1.xml
<com.example.android.apis.view.LabelView
android:background="#drawable/blue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:text="Blue"app:textSize="20dp"/>
This is contained in a LinearLayout with a namespace attribute:
xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"