I can't get styleable array of attrs - android

I am declaring a styleable view with attrs, and I created the file myview_attrs.xml this simple way:
<resources>
<declare-styleable name="TestStyleable">
<attr name="testAttr" format="integer"/>
</declare-styleable>
</resources>
Then, I want to load this attr in my code:
void loadAttributes(AttributeSet attrs) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.);
}
After R.styleable. , with ctrl-SPACE, these are the options I am given:
That is obviously wrong. Indeed, I can't select R.styleable.TestStyleable, because it's not proposed in the menu, but only R.styleable.TestStyleable_testAttr, that does not make sense.
Of course, if I choose the second one it gives me error, because a int[] is expected and I put an int. On the other side, if I manually write R.styleable.TestStyleable fails with "Cannot resolve symbol".
What am I missing here??
Update: this ended to be an Android Studio bug.

As #Yurii Tsap stated, this is an Android Studio bug, and it finally got fixed by making
File -> Invalidate Caches / Restart

Related

Android: Theme.resolveAttribute returns 0 cause Resources$NotFoundException: Resource ID #0x0

Short Question: Resources.Theme.resolveAttibute(attrId, typVal, true) returns typVal.resourceId is 0, cause that exception. This ResourceReader.getResourceId() works well in all places of whole app. But randomly, app update or after several restarts this exception occured because TypedValue.resourceId is 0.
Long Question:
I'm getting ResourcesNotFoundException on app restart unfortunately I can't determine when this error occurs. When I restart (close, kill, restart, update, setup) my app several times in a minute at last my app gives this RNFE on first resource read line.
Stack trace:
Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0
at android.content.res.Resources.getValue(Resources.java:2331)
at android.content.res.Resources.getColor(Resources.java:2013)
at com.my.app.navi.NavigationFragment.setUp(NavigationDrawerFragment.java:570)
at com.my.app.main.MainActivity.onCreate(MainActivity.java:1071)
It's hard to generate that exception but in Google Play Developer Console I can see a lot of exception generated by other devices.
I looked up a lot answers for that exception but nor rebuild, String.ValueOf(int), resource add solved my problem.
I have several build flavors for different styled and featured app. Because of that I use attr style reference for resources. All flavors has different res folders. main res folders has attrs.xml for reference colors, drawables and images. All the other code and xml layout files has R.attrs references
For explain my situation clearly this is main res attrs.xml
<declare-styleable name="Colors">
<!--<<<<<<<<<<<<<<<<<<<<< COLORS >>>>>>>>>>>>>>>>>>>>>>>>>>>>-->
<attr name="c_pressed_button_back" format="color"/>
<attr name="c_window_back" format="color"/>
<attr name="c_navigation_drawer_back" format="color"/>
flavor_one style.xml
<!--<<<<<<<<<<<<<<<<<<<<<<<<< COLORS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>-->
<item name="c_pressed_button_back">#color/c_theme_pressed_button_back</item>
<item name="c_window_back">#color/c_theme_window_back</item>
<item name="c_navigation_drawer_back">#color/c_theme_navigation_drawer_back</item>
flavor_one colors.xml
<color name="c_theme_pressed_button_back">#color/c_theme_red</color>
<color name="c_theme_window_back">#color/c_theme_green</color>
<color name="c_theme_navigation_drawer_back">#color/c_theme_blue</color>
With these settings I wrote this class for resource reading.
public class ResourceReader
{
public static int getResourceId(Resources.Theme thm, int attrId)
{
int returnValue = 0;
TypedValue typedValue = new TypedValue();
try {
thm.resolveAttribute(attrId, typedValue, true);
returnValue = typedValue.resourceId;
}
catch (Exception ex) // Resource cannot resolved
{
ex.printStackTrace();
}
if(returnValue == 0)
{
Log.e("yucel", "Resource resolved result is 0 #thm:" + thm + " attrid:" + attrId + " typdata:" + typedValue.data + " typtyp:" + typedValue.type + " ");
}
return returnValue;
}
}
And finally I use resources like
int back_color_id = ResourceReader.getResourceId(appData.appContext.getTheme(), R.attr.c_navigation_drawer_back);
int back_color= appData.appRes.getColor(back_color_id);
mDrawerLayout.setColor(back_color);
At the line of getColor(back_color_id) exception will be thrown. Because of back_color_id is equal to 0. In resource reader thm.resolveAttribute(attrId, typedValue, true);
I think whole code statements looks ok. Because whole app and 99 percent of use this structure works well. Problem occurs after several restarts and randomly at resource reading. Something must be changed in that situtation. Is there any method to check is resources in a proper state like Context.isResourceLoading() or Resoureces.isLoaded()?
Is there is any one faced resource reading problem at randomly, after several restart or after updates?
I changed attr.xml reading to direct theme item reading
int shadow_color = appData.appRes.getColor(R.color.c_ld_navigation_shadow_color);
mDrawerLayout.setScrimColor(shadow_color);
This works well. But there is a problem about that. I create the attr.xml references for dynamic theme change and different flavor variables reference.
In a flavor_one desing has open dialog background as a color named = c_open_dialog_backcolor
On the flavor_two design this has a drawable reference as a xml named = d_open_dialog_back_pattern
But this two design has same java code with no difference at set like usign resource resolver with R.attr.dialog_bakground
Seems the problem generated by Resources.Theme.resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) can't read resources when app restarting or update.
I changed my code and delete all the attr.xml items, its seems works good for now. Thanks.

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

Facebook LoginButton for Android does not take login_text and logout_text values passed from XML

Facebook Sdk for Android does not take login_text and logout_text values passed from XML. It just ignores it. There is no documentation/example available on earth which uses this customization of the button.
<com.facebook.widget.LoginButton
xmlns:fb="http://schemas.android.com/apk/res-auto"
android:id="#+id/connectWithFbButton"
style="#style/com_facebook_loginview_default_style"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center_horizontal"
android:text="#string/connect_with_facebook"
fb:login_text="#string/connect_with_facebook"
fb:logout_text="Connecting with facebook" />
It always says Login In or Log Out. How can I use this property? I tried debugging through the LoginButton code but in vain. It never goes through any of the constructors of LoginButton() and hence cannot parse my custom parameters.
Did someone face this issue?
Solved!!
Add string with name "com_facebook_loginview_log_in_button" to strings.xml located in res>values>strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="com_facebook_loginview_log_in_button">Connect</string>
<string name="com_facebook_loginview_log_out_button">Your Logout</string>
</resources>
Your first solution is correct.
It didn't worked because you've defined the style atrribute:
style="#style/com_facebook_loginview_default_style"
From the LoginButton source code:
public LoginButton(Context context, AttributeSet attrs) {
super(context, attrs);
if (attrs.getStyleAttribute() == 0) {
do stuff ...
}
}
So, it will only look at the defined attribute "login_text" if you leave "style" attribute undefined.
Gabriel is spot on. To fix this, go to LoginButton.java in Facebook SDK and move the parseAttributes call
parseAttributes(attrs)
to the bottom so that it always runs.
Whole method will look like this :
public LoginButton(Context context, AttributeSet attrs) {
super(context, attrs);
if (attrs.getStyleAttribute() == 0) {
// apparently there's no method of setting a default style in xml,
// so in case the users do not explicitly specify a style, we need
// to use sensible defaults.
this.setTextColor(getResources().getColor(R.color.com_facebook_loginview_text_color));
this.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimension(R.dimen.com_facebook_loginview_text_size));
this.setPadding(getResources().getDimensionPixelSize(R.dimen.com_facebook_loginview_padding_left),
getResources().getDimensionPixelSize(R.dimen.com_facebook_loginview_padding_top),
getResources().getDimensionPixelSize(R.dimen.com_facebook_loginview_padding_right),
getResources().getDimensionPixelSize(R.dimen.com_facebook_loginview_padding_bottom));
this.setWidth(getResources().getDimensionPixelSize(R.dimen.com_facebook_loginview_width));
this.setHeight(getResources().getDimensionPixelSize(R.dimen.com_facebook_loginview_height));
this.setGravity(Gravity.CENTER);
if(isInEditMode()) {
// cannot use a drawable in edit mode, so setting the background color instead
// of a background resource.
this.setBackgroundColor(getResources().getColor(R.color.com_facebook_blue));
// hardcoding in edit mode as getResources().getString() doesn't seem to work in IntelliJ
loginText = "Log in";
} else {
this.setBackgroundResource(R.drawable.com_facebook_loginbutton_blue);
initializeActiveSessionWithCachedToken(context);
}
}
parseAttributes(attrs);
}
both style and login_text are taken under consideration now. Works fine for me.
I ended up just having to change the text in the FacebookSDK source.
The login string is com_facebook_loginview_log_in_button located in FacebookSDK/res/values/strings.xml
As a shortcut, you can change the login button text directly in FB SDK 4.0 in com.facebook.login.widget.LoginButton class->setButtonText() method
I tried many of these solutions but nothing works, finally I came to an end with :
Locale loc = Locale.FRENCH;
loginButton = (LoginButton)findViewById(R.id.fb_login_button);
loginButton.setTextLocale(loc);
This changes the text to the locale you set and also the confirm dialogs, at least what I need.
Hope this helps.

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 ..
}

Android Custom Control namespace issue

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)

Categories

Resources