TagMatcher
The interface used by the inflation helpers to select Views using custom criteria.
On their own, the helpers only look for tags with the library's app:clipOutlineShadow attribute. For those cases where modifying the relevant layouts is impossible or infeasible, any number of TagMatchers can be provided to the helpers in order to select Views by any other criteria necessary. Like the inflation helpers, these matchers can be created and applied in either XML resources, or in code.
Creating matchers in resources:
Matchers created in XML can only compare against the layout tag names and android:id values. They are defined in res/xml/ files with a very simplistic language: the <id> and <name> tags, and the android:id, android:name, and app:matchRule attributes (note the app prefix). The parser is extremely lenient and simply ignores everything else.
The following snippet demonstrates all of the recognized element compositions:
<matchers
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<id android:id="@id/target_button" />
<id android:name="target_button" />
<id android:name="target_" app:matchRule="startsWith" />
<name android:name="ImageButton" />
<name android:name="Button" app:matchRule="endsWith" />
</matchers>These all will match an <ImageButton> with android:id="@+id/target_button".
An <id> element creates a TagMatcher that matches either the exact layout ID int using the android:id attribute, or the ID name using android:name and an app:matchRule (see MatchRule), which is equals by default.
The <name> element creates a TagMatcher that matches against the layout XML tag names, again using the android:name and app:matchRule attributes.
The res/xml/ files can be supplied to the inflation helper in a few different ways.
When using a zero-argument attach*ShadowHelper overload, or when the inflation helper itself is set through resources, it looks for an XML file reference first in the shadowTagMatchers theme attribute. For example:
<style name="Theme.YourApp" parent="Theme.…">
…
<item name="shadowTagMatchers">@xml/matchers</item>
</style>If there isn't one there, it then looks for a <meta-data> element in the manifest, first in the <activity> element, then in the <application>.
<application …>
<activity
android:name=".YourActivity"
android:theme="@style/Theme.YourApp">
<meta-data
android:name="com.zedalpha.shadowgadgets.SHADOW_TAG_MATCHERS"
android:resource="@xml/matchers" />
</activity>
<!-- Also valid in the application. -->
</application>Alternatively, an XML file can be passed directly to the helper in code, using the appropriate attach function overload:
class YourActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
// All of the attach*ShadowHelper functions have this overload.
attachShadowHelper(R.xml.matchers)
super.onCreate(savedInstanceState)
…
}
}Creating matchers in code:
TagMatcher is simply an interface, so it can easily be implemented to perform whatever other checks are necessary to select target Views from the available information. The fully constructed View, its tag name, and the AttributeSet pulled from the XML are all passed in to the match function.
The two predefined matchers that are available in XML are accessible here through the idMatcher and nameMatcher functions. For example, this snippet creates the exact same matcher list as the XML example above:
class YourActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
// All of the attach*ShadowHelper functions have this overload.
attachShadowHelper(
listOf(
idMatcher(R.id.target_button),
idMatcher(matchName = "target_button"),
idMatcher(
matchName = "target_",
matchRule = MatchRule.StartsWith
),
nameMatcher("ImageButton"),
nameMatcher("Button", MatchRule.EndsWith)
)
)
super.onCreate(savedInstanceState)
…
}
}