Create Custom Compound View in Android with Attributes - android

I have created a custom compound view inside a library application and everything was OK. When I add custom attributes to view, I always get default values. I followed this steps with only one difference: my view is in a library project.
/res/values/attrs.xml
<resources>
<declare-styleable name="DatePickerView">
<attr name="showToday" format="boolean" />
<attr name="calendar" format="enum">
<enum name="jalali" value="0" />
<enum name="gregorian" value="1" />
</attr>
</declare-styleable>
</resources>
Layout file that contains view:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:farayan="http://schemas.android.com/apk/lib/net.farayan.android.view"
...
<net.farayan.android.view.datepicker.DatePickerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
farayan:showToday="false"
farayan:calendar="gregorian"/>
...
Component's code:
int calendar;
boolean showToday;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePickerView, 0, 0);
try {
calendar = a.getInteger(R.styleable.DatePickerView_calendar, 0);
showToday = a.getBoolean(R.styleable.DatePickerView_showToday, true);
} finally {
a.recycle();
}
calendar and showToday are always 0 and true respectively. Any idea?

It looks like something is not right here:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:farayan="http://schemas.android.com/apk/lib/net.farayan.android.view"
What about change to:
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:farayan="http://schemas.android.com/apk/res/net.farayan.android.view"
net.farayan.android.view is your app root namespace.
update1
xmlns:farayan="http://schemas.android.com/apk/res/your_main_app_package"
Here is am example. It use a view defined in the library project.

If we add new compound view code and its attributesinside project, we should add this at the beginning of layout:
xmlns:custom="http://schemas.android.com/apk/res/your_main_app_package
and if new compound view is inside a library project linked to our peoject, we should add this:
xmlns:custom="http://schemas.android.com/apk/res-auto
Link: https://stackoverflow.com/a/10217752/1152549

Related

How to Bind the Wikitude aar file in xamarin

Hi I am trying to bind wikitude .aar fine in xamarin...I am having some issues
Com.Wikitude.Tracker.IObjectTrackerListener.cs(47,47): Error CS0102: The type 'TargetsLoadedEventArgs' already contains a definition for 'p0' (CS0102) (AarBinding)
Com.Wikitude.Tracker.IObjectTrackerListener.cs(14,14): Error CS0102: The type 'ErrorLoadingTargetsEventArgs' already contains a definition for 'P1' (CS0102) (AarBinding)
I tried to use the Metadata.xml as
<attr path="/api/package[#name='Com.Wikitude.Tracker']/class[#name='ErrorLoadingTargetsEventArgs']/field[#name='p0']" name="managedName">p0_2</attr>
But it is now working any suggestions Please ?
Hi I was as able to fix this issue..It may be helpful for others
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<attr path="/api/package[#name='com.wikitude.tracker']/interface[#name='ObjectTrackerListener']/method[#name='onTargetsLoaded']/parameter[1]" name="managedName">tracker</attr>
<attr path="/api/package[#name='com.wikitude.tracker']/interface[#name='ObjectTrackerListener']/method[#name='onErrorLoadingTargets']/parameter[1]" name="managedName">tracker</attr>
<attr path="/api/package[#name='com.wikitude.tracker']/interface[#name='ObjectTrackerListener']/method[#name='onErrorLoadingTargets']/parameter[2]" name="managedName">errorCode</attr>
<attr path="/api/package[#name='com.wikitude.tracker']/interface[#name='ObjectTrackerListener']/method[#name='onErrorLoadingTargets']/parameter[3]" name="managedName">errorMessage</attr>
<attr path="/api/package[#name='com.pbar.samples']/class[#name='StartActivity']"
name="visibility">public</attr>
</metadata>

Accepting a text style for a custom view

So I am writing my own custom view, that has both a TextView and an EditText within it. What I am trying to do is let the user set a text style for each one individually, like this:
<declare-styleable name="InputRow">
<attr name="descriptionTextStyle" format="string" />
<attr name="valueTextStyle" format="string" />
</declare-styleable>
I thought this would work, so that in XML I could say:
app:descriptionTextStyle="bold"
app:valueTextStyle="italic"
However, the problem comes when I am trying to read from the typed array. I can get the string:
if(typedArray.hasValue(R.styleable.InputRow_descriptionTextStyle)) {
setDescriptionTextStyle(typedArray.getString(R.styleable.InputRow_descriptionTextStyle));
}
but when I want to call descriptionTextView.setTypeface(Typeface tf, int style) I need an integer value for the second parameter, which I don't have.
I can't change the style to be an int format, because then ="bold" would be invalid, so I'm at a loss for how to get the text style.
Thanks to the suggestion from pskink, I took a look at how Android defines the style:
<!-- Default text typeface style. -->
<attr name="textStyle">
<flag name="normal" value="0" />
<flag name="bold" value="1" />
<flag name="italic" value="2" />
</attr>
Given that, I was able to update my custom attribute accordingly:
<attr name="descriptionTextStyle">
<flag name="normal" value="0" />
<flag name="bold" value="1" />
<flag name="italic" value="2" />
</attr>
Then I was able to setup my item by calling app:descriptionTextStyle="bold" and in the class I call typedArray.getInt() and call the setTypeface() method as I said. Thanks for the help!
You can use the
public void setTypeface(Typeface tf);
method, it only requires a typeface parameter.
Also for converting string to typeface you can do something like this:
switch (typefaceString) {
case SANS:
tf = Typeface.SANS_SERIF;
break;
case SERIF:
tf = Typeface.SERIF;
break;
case MONOSPACE:
tf = Typeface.MONOSPACE;
break;
}

Understanding the xmlns attribute in an Android layout

I have only recently had to set the xmlns attribute in an Android layout file. Initially when I was adding a third-party control, certain attributes in the control's XML didn't have a prefix to identify the namespace. When I ran my app, the control was displayed but those attributes that didn't have the namespace prefix were ignored. Only after adding the xmlns to the top of my file and adding the prefix to the attributes did those attributes get recognized at run time. Here is what the corrected code looks like:
xmlns:fab="http://schemas.android.com/apk/res-auto"
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="#+id/ivFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
fab:fab_icon="#drawable/ic_fab_star"
fab:fab_colorNormal="#color/pink_500"
fab:fab_colorPressed="#color/pink_100"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
android:visibility="visible"
/>
The xmlns prefix her is 'fab'. What I don't understand is that without the namespace and prefix, the app compiles without any errors. Why doesn't Android Studio complain that it cannot find fab_icon? Why does it just ignore these attributes? I have seen a number of posts throughout stackoverflow on different topics where someone has indicated to leave out the prefix and then the code worked. So I'm at a loss to understand what's going on. In some problems (like mine) having the prefix is required but in others it isn't? Is this an issue with different versions of Android Studio or the SDK versions?
Yes. Even you can define your own custom layout attributes.
Step 1: Create a subclass of a view.
class PieChart extends View {
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
Step 2: Define Custom Attributes with <declare-styleable> in res/values/attrs.xml .
<resources>
<declare-styleable name="PieChart">
<attr name="showText" format="boolean" />
<attr name="labelPosition" format="enum">
<enum name="left" value="0"/>
<enum name="right" value="1"/>
</attr>
</declare-styleable>
</resources>
Step 3: Using those attributes inside your layout xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
<com.example.customviews.charting.PieChart
custom:showText="true"
custom:labelPosition="left" />
</LinearLayout>
Step 4: Applying custom attributes to your view.
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.PieChart,
0, 0);
try {
mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
} finally {
a.recycle();
}
}
Step 5: Adding properties and events
Attributes are a powerful way of controlling the behavior and appearance of views, but they can only be read when the view is initialized. To provide dynamic behavior, expose a property getter and setter pair for each custom attribute. The following snippet shows how PieChart exposes a property called showText
public boolean isShowText() {
return mShowText;
}
public void setShowText(boolean showText) {
mShowText = showText;
invalidate();
requestLayout();
}
For more information and details, read this link.

Styleable cannot be resolved

Here is the code I am using:
public ASSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray sharedTypedArray = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.ASSwitch,
0, 0);
try {
onText = sharedTypedArray.getText(R.styleable.ASSwtich_onText, null);
} finally {
sharedTypedArray.recycle();
}
}
Here is the attrs.xml file (added to values folder):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ASSwitch">
<attr name="onText" format="string" />
<attr name="offText" format="string" />
<attr name="onState" format="boolean" />
<attr name="toogleDrawable" format="string" />
<attr name="frameDrawable" format="string" />
</declare-styleable>
</resources>
The answers in these questions couldn't fix the problem. Please don't consider my question as duplicate.
Android Hello, Gallery tutorial -- "R.styleable cannot be resolved"
Android: How to Declare Styleable in R.java?
R.styleable can not be resolved, why?
R.styleable cannot be resolved
Update: It seems that I was importing the wrong R class. It shall be the application's R class not android.R.
Check your imports:
Wrong: Android.R
Correct: com.example.yourproject.R
I had the same error when made this customized view. Maybe when follow the guiding step, the helper tool automatically inserts this wrong import.
It seems that I was importing the wrong R class. It shall be the application's R class not android.R

Resources$NotFoundException in Graphical Layout ADT preview (but app actually Works)

My problem is that loading an array of strings defined in XML works in the app but will result in an error in the ADT Graphical Layout preview.
Now I can't see any graphics in the Graphical Layout because of this error, and it's difficult to work with other graphics.
But the view is loading and displaying the strings fine if I build and run my app.
So I suppose my code is correct but either:
I am missing some limitations of the Graphical Layout preview and some workaround
or perhaps I'm missing something obvious and doing things wrong even if it seems to work in the app
I have a custom view where I get an array defined by me in an array.xml file.
public class ScoreTable extends View {
[...]
#Override
protected void onDraw(Canvas canvas) {
[...]
int score_vals[] = getResources().getIntArray(R.array.score_vals);
[...]
}
[...]
}
My array is defined in res/values/array.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="score_vals">
<item >10</item>
<item >20</item>
<item >50</item>
</array>
</resources>
Graphical Layout is blank and says:
Int array resource ID #0x7f050000
Exception details are logged in Window > Show View > Error Log
But of course I have "public static final int score_vals=0x7f050000;" in R.java!
The details of this error are in a 50-deep stack, but resumes to this:
android.content.res.Resources$NotFoundException: Int array resource ID #0x7f050000
at android.content.res.Resources.getIntArray(Resources.java:405)
at com.threecats.poker.ScoreTable.onDraw(ScoreTable.java:53)
at android.view.View.draw(View.java:6740)
[...]
So, should getResources().getXXXArray() work in the context of a ADT Graphical Layout preview?
I would like to mention that I tried with both "array" and "array-integer" in the XML, and both work in the app but not in the preview.
Also I tried to save the Context from the constructor of the view in a private Context member... didn't help either.
Your code is alright but unfortunately there are still some bugs in ADT plugin and there is one of them. Layout Editor has troubles with rendering custom views. I had the same issue and the only workout I have found is checking View.isInEditMode and initializing int array in some other way but not from resources. So your code will look like this:
int score_vals[];
if (isInEditMode()) {
score_vals = { 10, 20, 50 };
} else {
score_vals = getResources().getIntArray(R.array.score_vals);
}
And by the way don't create or load any resources in your onDraw methods. I suppose getResources().getIntArray uses some sort of caching but anyway your perfomance may suffer.
I found a kind of a workaround whereby you have to hijack android's own attributes to get access to resources in the designer.
The following should provide the idea, but you would have to find a native android property of type int[]
This custom view XML should render in the graphical layout preview while using resources
<!-- Could override individual attributes here too rather than using a style -->
<com.github.espiandev.showcaseview.ShowcaseView
style="#style/ShowcaseView"/>
styles.xml - Style specifying some of the resources to use
<style name="ShowcaseView" parent="match_fill">
<!--# Cling drawable -->
<item name="android:src">#drawable/cling</item>
<!--# Title #-->
<item name="android:contentDescription">#string/showcase_title</item>
<!--# Description #-->
<item name="android:description">#string/showcase_description</item>
<!--# Button Text #-->
<item name="android:text">#string/ok</item>
<item name="sv_titleTextColor">#33B5E5</item>
<item name="sv_detailTextColor">#FFFFFF</item>
<item name="sv_backgroundColor">#3333B5E5</item>
<item name="sv_buttonBackgroundColor">#3333B5E5</item>
<item name="sv_buttonForegroundColor">#33B5E5</item>
</style>
attrs.xml - Custom attribute definition compatible with design-time preview
<!-- The android attrs assume the corresponding android format / data type -->
<declare-styleable name="ShowcaseView">
<!--# Cling drawable -->
<attr name="android:src"/>
<!--# Title #-->
<attr name="android:contentDescription"/>
<!--# Description #-->
<attr name="android:description"/>
<!--# Button Text #-->
<attr name="android:text"/>
<attr name="sv_backgroundColor" format="color|reference" />
<attr name="sv_detailTextColor" format="color|reference" />
<attr name="sv_titleTextColor" format="color|reference" />
<attr name="sv_buttonBackgroundColor" format="color|reference" />
<attr name="sv_buttonForegroundColor" format="color|reference" />
</declare-styleable>
ShowcaseView.java - Using the custom attributes in the custom view
public ShowcaseView(Context context) {
this(context, null, R.styleable.CustomTheme_showcaseViewStyle);
}
public ShowcaseView(Context context, AttributeSet attrs) {
this(context, attrs, R.styleable.CustomTheme_showcaseViewStyle);
}
public ShowcaseView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// Get the attributes for the ShowcaseView
final TypedArray styled = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ShowcaseView, 0, 0);
showcase = styled.getDrawable(R.styleable.ShowcaseView_android_src);
titleText = styled.getString(R.styleable.ShowcaseView_android_contentDescription);
subText = styled.getString(R.styleable.ShowcaseView_android_description);
buttonText = styled.getString(R.styleable.ShowcaseView_android_text);
backColor = styled.getInt(R.styleable.ShowcaseView_sv_backgroundColor, Color.argb(128, 80, 80, 80));
detailTextColor = styled.getColor(R.styleable.ShowcaseView_sv_detailTextColor, Color.WHITE);
titleTextColor = styled.getColor(R.styleable.ShowcaseView_sv_titleTextColor, Color.parseColor("#49C0EC"));
styled.recycle();
// Now make use of the fields / do further initialization ..
}

Categories

Resources