Let's say I have an application with two themes: male and female. Themes simply change the color palette and several drawings to suit the user's preferences.
How about we pretend that you are doing something else? This is an anti-design pattern that associates certain colors based on gender (for example, “girls like pink”).
This does not mean that your technical goal is bad, it’s just a really stereotypical example.
For example, I can add a pirate theme, and then "Submit" will be "Arrrrgh!"
Only if “Cancel” is displayed on “Avast!”.
How can I change the lines throughout the application through custom themes?
You did not say where these lines come from. Are they string resources? Database Records? What do you get from the web service? Something else?
I assume at the moment that these are string resources. By definition, you will need to have N copies of rows, one per topic.
Since gender and pirated status are not tracked by Android as possible resource set qualifiers, you cannot have these string resources in different resource sets. Although they may be in different files (for example, res/values/strings_theme1.xml ), file names are not part of the resource identifiers for strings. So you have to use some kind of prefix / suffix to keep track of which lines belong to those (e.g. @string/btn_submit_theme1 ).
If these lines do not change at run time - that’s all that is in your layout resource, you can take a page from Chris Jenkins’s Calligraphy Library . It has its own subclass of LayoutInflater , used to overload some standard XML attributes. In his case, the focus is on android:fontFamily , where he supports this mapping to the font file in assets.
In your case, you can overload android:text . In your layout file, instead of pointing to any of your actual lines, you could get this base name of the string resource you need, without any topic identifier (for example, if the real lines are @string/btn_submit_theme1 and kin, you could have android:text="btn_submit" ). Your subclass LayoutInflater should capture this value, add a suffix for the theme name, use getIdentifier() on your Resources to find the actual resource identifier of the string and from there bind the string to your theme.
A variant of this would be to put the base name in android:tag instead of android:text . android:text can point to one of your real line resources to help with GUI design, etc. Your LayoutInflater will grab the tag and use it to get the correct line at runtime.
If you replace the text with other text torn from the subject line resources, you can isolate your get-the-string-given-the-base-name logic in a static utility, wherever you apply it.
If used correctly, this process will require a little work, it will scale to arbitrary complexity in terms of the number of visible widgets and user interface lines. You still need to remember adding values ​​for all topics for any new lines that you define (bonus points for creating a custom Lint check or Gradle task for checking this).