Custom state drawables not working in Library Projects - android

Any searches for any information on how to provide your own custom state for use in a drawable state list selector pulls up very little but almost all of them (here and elsewhere) refer to this google groups post.
I have getters and setters like this: (Not included in the above post, but using their wording to keep it simple)
public void setFried(boolean fried){
if(mFried != fried){
mFried = fried;
refreshDrawableState();
}
}
public void isFried(){
return mFried;
}
I have been trying to get it to work for the last couple hours and nothing seems to be working. It just simply does not change the appearance. I watched what happened as it called onCreateDrawableState(), and I watched what would come out of getDrawableState() after I changed the custom state. The custom state values are in fact appearing in the drawableState array.
Since I can see the state is actually being merged into the array, and since it seems to be completely ignoring any of my custom state in the selector, I think the xml must be wrong.
Here is what the post suggested:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/my.app.package">
<item android:drawable="#drawable/item_baked" state_baked="true"
state_fried="false" />
<item android:drawable="#drawable/item_fried" state_baked="false"
state_fried="true" />
<item android:drawable="#drawable/item_overcooked" state_baked="true"
state_fried="true" />
<item android:drawable="#drawable/item_raw" state_baked="false"
state_fried="false" />
</selector>
Can you really just write state_fried and state_baked or do they need a prefix like app:state_fried? If I try adding a prefix I get a Console error like: No resource identifier found for attribute 'state_fried' in package my.app.package
Has anyone actually got custom states to work? Is the referenced post all you need to get this to work or is there something wrong with it or missing?
I don't know if it makes any difference but I am using an Android Library Project and the selector and the attr.xml is in the Library project.
Thanks
Update
Looks like the problem is that Library Projects don't play well with custom attributes. See here, here, here.
Haven't seen much of a workaround unfortunately...

I wrote that original question. IIRC, that was when Android was in beta, and things have changed a bit. Custom attributes do indeed work; I use them. You do indeed need the app: prefix for custom state attributes. You also need to substitute your app's package in place of my.app.package in the xmlns declaration.

use
xmlns:app="http://schemas.android.com/apk/lib/my.app.package
for attributes declared in the library.

Related

Override layout xml from android framework

Problem
I want to override a layout file from android namespace, e.g. R.layout.popup_menu_item_layout (which is referenced from code as com.android.internal.R.layout.popup_menu_item_layout). By saying override, I assume declaring an xml file in the project which would be prioritized over the layout that framework owns.
Note, this is just an example layout, so the question concerns to each layout that's present in sdk/platforms/android-XX/data/res/layout directory.
What I've tried
tools:override
There's an undocumented tools:override tag available, which overrides specific resources. See this answer for an example, which overrides values from Design Support Library, not from Android framework.
Applying tools:override="true" to the root tag of the layout won't take effect.
XML layout references - refs.xml
As described in this post, declaring a refs.xml file in /values/ directory with following content:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="layout" name="activity_main">#layout/activity_second</item>
</resources>
will refer to activity_second.xml once activity_main.xml is used. There's an answer that suggests using this technique in order to substitute Snackbar's layout.
This also won't take effect.
Question
Is there any legitimate way to override/substitute a layout file from android package?
I know this is an old question but I also wanted to override a library layout with my own, here's how I did it.
The layout in question was called design_bottom_navigation_item
In refs.xml I added the following:
<resources xmlns:tools="http://schemas.android.com/tools">
<item name="design_bottom_navigation_item" type="layout" tools:override="true">#layout/bottom_navigation_item</item>
</resources>
There are 4 parts to this which I'll explain.
Name: This is the name of the layout you want to override
Type: The type of resource you are trying to override, in this case a layout.
tools:override: This is how you tell Android Studio to override the library layout with your own.
Value: This is where you specify what resource you want to use instead.
You can do this with any resource type this way.
What is that you're trying to do?
If the idea to only replace how the menu-item will look like, you can try the following:
Create a custom MyMenuAdapter extends MenuAdapter
Override the getView method to return the view from your adapter.
You are trying to customise your sdk on the application itself, at runtime.
That's just not how it works.
If you use an SDK on your project(on any technologies), and you need to modify some behavior, you will tweak this SDK and after that, compile your project with this news customized version.
Trying to modify it at runtime is not a good idea.
You will face multiple issues (retro compatibility, security trigger, TREBLE incompatibility , dependency issue, etc)
You have 4 possibilities to do what you want:
Make your own android rom where you will apply your modification
Copy the resources you need to modify on a fake xmlObject with the tag, after the onPostCreate of your application, you will be able to modify the when inflation. You can generalize this behavior and it will simulate an sdk overlay.
Make your own sdk :)
Multi-level reflection, but, no way you succeed with a stable version
Of course, none of this solutions is applicable for a public app.
don't know your issue have fixed or not but simple solution for this is create new layout that is same layout name of framework (in this case is popup_menu_item_layout). Then go to android google source to copy xml content popup_menu_item_layout
So you can custom anything u want. But remember don't change any id of views.

Android Layout - when to use app: vs android:?

I've been writing some Android apps but I don't really understand when to use app: and when to use android:. When styles are not being applied the way they're supposed to, I use trial and error and sometimes find that using app: instead of android: solves the issue but I don't understand why. It'd be great if someone could point me in the right direction. Thanks!
You can use the app namespace to have app compatibility with older API versions.
For example
app:srcCompat="#drawable/customborder" has the same effects with
android:background="#drawable/customborder"
The difference is that the first will work correctly with older API's and the second will not display what you would like.
You are talking about custom namespace.In android we can create custom views in additional to already available views.
As per in Google developer docs..
To add a built-in View to your user interface, you specify it in an XML element and control its appearance and behavior with element attributes. Well-written custom views can also be added and styled via XML. To enable this behavior in your custom view, you must:
Define custom attributes for your view in a resource element
Specify values for the attributes in your XML layout
Retrieve attribute values at runtime
Apply the retrieved attribute values to your view
Once you define the custom attributes, you can use them in layout XML files just like built-in attributes. The only difference is that your custom attributes belong to a different namespace. Instead of belonging to the http://schemas.android.com/apk/res/android namespace, they belong to http://schemas.android.com/apk/res/[your package name]
So for if you use default views you can use android namespace and if you want to set and use attributes for custom view you can define your own name.
Refer this
If you take a look at the beginning of the your layout xml files (in which you used app:) you will (probably) find lines like this:
<?xml version="1.0" encoding="utf-8"?>
<SOME_LAYOUT xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
in this case app: namespace will be used for custom attributes, specified by you inside attrs.xml file or by someone else in one of used libraries.
Sometime the property with android only available in new Android version like
In this case, you should use app:... to make it work with older version.
moreover you will find two variants
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:app="http://schemas.android.com/apk/[packagename]"
the difference between xmlns lines is res-auto take care of resolving our package as sometime we will add .debug or .test in our package and we already provided the packageid of the app Ex:
xmlns:app="http://schemas.android.com/apk/com.test.io.debug"
xmlns:app="http://schemas.android.com/apk/com.test.io.test"

Where can I find the definition for ?android:attr/listItemFirstLineStyle

I tried digging around in https://github.com/android/platform_frameworks_base/tree/master/core/res/res and google but I can't seem to find it.
In general ?android:attr/... references the value of an attribute in the currently-applied theme (Referencing style attributes). Those attributes are defined in res/values/attrs.xml - however, there is no entry for listItemFirstLineStyle (neither in the current version nor in the first git contribution from 10/2008). The attribute seems to have appeared in very early versions of bothsimple_list_item_X.xml layouts though.
Using listItemFirstLineStyle in my own layout basically comes to the same result.

How to eliminate warning in android layout.xml: "missing contentDescription"

<ImageView style="#style/LoaderPrevNext.Next" />
using the styles
<style name="LoaderPrevNext">
<item name="android:layout_width">40dp</item>
<item name="android:layout_height">80dp</item>
<item name="android:layout_weight">0</item>
<item name="android:scaleType">fitXY</item>
</style>
<style name="LoaderPrevNext.Next">
<item name="android:src">#drawable/next_page</item>
<item name="android:contentDescription">#string/img_desc_next_page</item>
</style>
annoys me with the [Accessibility] Missing contentDescription attribute on image warning.
It disappears if I move or copy the contentDescription from the style to the ImageView tag, but as the src is defined in the style, I'd love to keep them together.
Guess it's simply an SDK bug, but some might got a workaround...
Clarification: The ImageView in question do have a content-description, defined in the LoaderPrevNext.Next style. The warning is false. I'm not interested in ideas on how to set the content description, or how to hack them empty.
In Eclipse Window->Preferences->Android->Lint Erroe Checking->Right Side Scroll Down Until Accessibility->Content Description->Severity->Select Ignore->Apply->yes
How To Suppress Android Accessibility Warning Missing contentDescription
Both of the existing answers to this question are technically correct, but I believe there is a better way. The first answer suggests turning off all contentDescription warnings. While this works, contentDescription is there for a reason, and perhaps should not be globally turned off for all content.
The second answer shows how to specify the contentDescription. While this does make the warning go away, it is not appropriate for all content and technically does not answer the question, although it is a valid work-around.
The Android documentation for lint provides the best solution, IMO, which is a mixture of providing contentDescription for some content, and suppressing the lint warning for other content:
Note that elements in application screens that are purely decorative
and do not provide any content or enable a user action should not have
accessibility content descriptions. In this case, just suppress the
lint warning with a tools:ignore="ContentDescription" attribute.
Therefore, Implement the following solution to remove all of the lint warnings:
Define contentDescription in your XML layout file with android:contentDescription="Your description here." for resources that provide interesting or
useful information to the user. And,
Add tools:ignore="ContentDescription" to purely decorative content or
images.
To disable missing content description warning in the whole project, add this to your build.gradle
android {
...
lintOptions {
disable 'ContentDescription'
}
}
If you do not wish to turn off / ignore the lint warnings you could define an empty string in strings.xml
string.xml:
<string name="empty"></string>
and then in your xml just set the value
<ImageView
android:id="..."
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/empty"/>
contentDescription tag is used for screen reading feature of android. you can add a string about what is your image is or you can just suppress/ignore this warning by adding the following tag.
tools:ignore="ContentDescription"
< ImageView
android:id= ...
android:layout_width= ...
...
android:contentDescription="your description comes here. get from strings xml if its a string"
/>
Why would you want to have image description in Style.
The purpose of styles is to have an ability to change something in one place which is reflected in several places.
Same goes for #string resource. Simply don't put image description in style. Leave #string. Once needed - change that string itself.
I think that the correct solution is to report this as a bug in Android Studio, though I doubt that they will fix it anytime soon (from experience with my bug reports about other things). https://developer.android.com/studio/report-bugs
I'm sorry that so far you have had only off-topic answers that totally ignore the key elements of your question, and answers that claim that styles aren't meant for doing what you want to them (even though the docs never warn against what you are trying to do). I came here because I have the same problem as you have (in 2023 and which I encountered around 2020). I don't see any sign of Android Studio / Android Lint offering an option for taking styles into account. It doesn't even look like there is a point to not taking styles into account, therefore there shouldn't be an option for this, any rule that checks presence or content of specific attributes should also look up the style specified by style="".

When should you use `#+id` instead of `#id`?

I have a bunch of Views in a <merge>, and I included that <merge> into a RelativeLayout. I try to refer to the IDs of those included Views to act as anchors for my other Views, but Eclipse complains that the IDs are not resolving. I found a workaround by using #+id rather than #id when I first refer to them rather than when I actually define the objects they refer to. I've already defined the two IDs in a Style and in the included <merge> where they are declared, so it feels a bit inefficient if I keep repeating the definition of the ID.
Is this the correct way of doing it? I'm assuming it's bad cause the '+' is another initialization. My current hypothesis is that you should use #+id when you first use the ID rather than when you initialize the object that the ID is going to represent, a bit like C/C++ and how they require at least a function prototype in the lines prior to the actual code that uses the function.
Another question I have is when you use the GUI-based UI builder of Eclipse, I noticed that they always use #+id rather than #id. Is this acceptable, cause it seems inefficient to me; it's as if the application will be spending more time determining whether or not the ID has been declared in R.id.
Using #+id format tells the Android asset compiler to assign an ID to your element, it isn't actually an id itself. So if I use #+id/myNewId the asset compiler will create a new id named myNewId and provide a number for it. The actual number can be accessed from your code as R.id.myNewId.
If you use an #id, the compiler will look for R.id.id. You can define your own id's in XML files, as explained here: http://developer.android.com/guide/topics/resources/more-resources.html#Id. You could create your own file in res/values/[your_filename].xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item
type="id"
name="id_name" />
</resources>
and then refer to #id_name, for e.g.
You can also use the Id's defined in the Android namespace: #android:id/empty
This is well explained in the Android documentation: http://developer.android.com/guide/topics/ui/declaring-layout.html#id
There's also some further discussion here: android:id what is the plus sign for

Categories

Resources