Android themes and styles without magic. And how to cook them with SwitchCompat
In a previous article, we looked at how to use themes and styles at the code level, using the custom view as an example. In this article, let's look at several ways to style a standard ui element, and in particular SwitchCompat.
Content
Introduction
New style for switchStyle
Style in layout
Style in theme. The topic is assigned through Manifest.
Style in the subject. The theme is assigned programmatically.
Other View
Introduction
Not always the default design of the standard UI element suits the designer. Let's look at how to change the appearance of an element using the example of SwitchCompat.
To solve the problem, we need:
- Create your own style for SwitchCompat.
- Somehow set this SwitchCompat style.
There are several ways to designate a SwitchCompat style, for example:
- Specify for each view in the layout of screens through the style attribute.
- Create a theme with an overridden switchStyle attribute and assign this theme in the manifest for the entire application or specific activity. This will change the look of the view for the entire application / activity.
- The topic can also be set programmatically in the activation code. If necessary, it can be changed on the fly.
New style for SwitchCompat
In the resources, create a new MySwitchStyle style, inherit the design from Widget.AppCompat.CompoundButton.Switch by setting parent. You may not inherit, but then you have to specify all the values, even which we do not plan to change.
To change something, you need to redefine the required attributes. Attributes can be found in the documentation.
In the documentation we see several attributes. They are indicated as if we were accessing them in code (for example, like R.styleable.SwitchCompat_android_thumb). I will decode only part of them so that there is no doubt. The purpose of the rest is easy to understand from the documentation.
In code | In xml |
SwitchCompat_android_thumb | android: thumb |
SwitchCompat_thumbTint | thumbTint |
SwitchCompat_track | track |
SwitchCompat_trackTint | trackTint |
- android: thumb - resource for the moving part of SwitchCompat
- track - resource for the fixed part of SwitchCompat
- thumbTint - allows you to paint the moving part in the desired colors depending on the state of SwitchCompat
- trackTint - allows you to color the stationary part in the desired colors depending on the state of SwitchCompat
As an example, change the color of the thumb (circle) - let it be orange when it is on, and green when it is off. Ugly, but clearly.
We will need a selector in the color folder of our resources. File selector_switch_thumb.xml
Now set the thumbTint attribute in our style.
Now all SwitchCompat, which somehow got MySwitchStyle style, will look in a new way.
Layout style
The most trivial and inflexible way.
- The style is applied when inflate the layout resource.
- We cannot influence software in any way.
- It is inconvenient to indicate each time in layout. And we can forget.
Style in the subject. Topic assigned via Manifest
Create an AppTheme theme and set the value of the switchStyle attribute. Value is our MySwitchStyle style.
The theme can be specified in the manifest for the entire application.
Or for a specific activity
Now all SwitchCompat will have a new look. No change in layout.
- Pros - We can change the appearance for the entire application immediately.
- Cons - on the fly you can’t change it.
Style in the subject. The theme is assigned programmatically
In order to set the theme for activation programmatically, you need to call the activation method setTheme (themeResId).
Let's change the theme of activity depending on the state of the Switch.
private const val KEY_CUSTOM_THEME_CHECKED = "KEY_CUSTOM_THEME_CHECKED"
class MainActivity : AppCompatActivity() {
private val preference by lazy {
PreferenceManager.getDefaultSharedPreferences(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
val isCustomThemeChecked = preference.getBoolean(
KEY_CUSTOM_THEME_CHECKED,
true
)
if (isCustomThemeChecked) {
setTheme(R.style.CustomTheme)
} else {
setTheme(R.style.StandardTheme)
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
customThemeCheckbox.isChecked = isCustomThemeChecked
customThemeCheckbox.setOnCheckedChangeListener { _, isChecked ->
preference.edit()
.putBoolean(KEY_CUSTOM_THEME_CHECKED, isChecked)
.apply()
recreate()
}
}
}
- Install the theme programmatically by calling setTheme. The method must be called before super.onCreate (savedInstanceState). In onCreate, we initialize fragments (when they are).
- Set the initial state of the Switch depending on the topic.
- We install a listener that, when changing the Switch, changes the theme in the settings and restarts the activity through the recreate () activation method.
Result
The rest of the code
Other View
In order to redefine the style for SwitсhView for the entire application, we redefined the value of the switchStyle attribute, we can guess that such attributes exist for other View.
For instance:
- editTextStyle
- checkboxStyle
- radioButtonStyle
How to look for them? I just watch the source through Android Studio.
We go into the topic, hold down ctrl, click on the parent of our topic. We look at how the guys from Google describe the topic. We look at which attribute is determined and from which style we can inherit. We use it.
A piece from the theme Base.V7.Theme.AppCompat.Light.
- @style/Widget.AppCompat.EditText
- @style/Widget.AppCompat.CompoundButton.CheckBox
-
@style/Widget.AppCompat.CompoundButton.RadioButton
- @style/Widget.AppCompat.Button
Resources
developer.android.com/guide/topics/ui/look-and-feel/themes
developer.android.com/reference/android/support/v7/widget/SwitchCompat.html#xml-attributes
P.S.
The article does not claim to be a complete reference. Code intentionally shortened. I set the task to give a general understanding - how it works and why it is needed. Then everything is easily looked for in the documentation and in standard resources.