这对我有用(需要 Android 4.1):
Switch switchInput = new Switch(this);
int colorOn = 0xFF323E46;
int colorOff = 0xFF666666;
int colorDisabled = 0xFF333333;
StateListDrawable thumbStates = new StateListDrawable();
thumbStates.addState(new int[]{android.R.attr.state_checked}, new ColorDrawable(colorOn));
thumbStates.addState(new int[]{-android.R.attr.state_enabled}, new ColorDrawable(colorDisabled));
thumbStates.addState(new int[]{}, new ColorDrawable(colorOff)); // this one has to come last
switchInput.setThumbDrawable(thumbStates);
请注意,“默认”状态需要最后添加,如此处所示。
我看到的唯一问题是开关的“拇指”现在看起来比开关的背景或“轨道”大。我认为那是因为我仍在使用默认的轨道图像,它周围有一些空白空间。但是,当我尝试使用这种技术自定义轨道图像时,我的开关似乎有 1 个像素的高度,只出现了一小段开/关文本。肯定有解决办法,不过我还没找到……
Android 5 更新
在 Android 5 中,上面的代码使开关完全消失。我们应该可以使用新的setButtonTintList 方法,但是这对于开关来说似乎被忽略了。但这有效:
ColorStateList buttonStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_checked},
new int[]{}
},
new int[]{
Color.BLUE,
Color.RED,
Color.GREEN
}
);
switchInput.getThumbDrawable().setTintList(buttonStates);
switchInput.getTrackDrawable().setTintList(buttonStates);
Android 6-7 更新
正如 Cheruby 在 cmets 中所说,我们可以使用新的 setThumbTintList,这对我来说就像预期的那样工作。我们也可以使用setTrackTintList,但这会将颜色作为混合颜色应用,结果在深色主题中比预期的要暗,在浅色主题中比预期的要亮,有时甚至到了不可见的程度。在 Android 7 中,我可以通过覆盖轨道 tint mode 来最小化这种变化,但在 Android 6 中我无法获得不错的结果。您可能需要定义额外的颜色来补偿混合。 (您有没有觉得 Google 不希望我们自定义应用的外观?)
ColorStateList thumbStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_checked},
new int[]{}
},
new int[]{
Color.BLUE,
Color.RED,
Color.GREEN
}
);
switchInput.setThumbTintList(thumbStates);
if (Build.VERSION.SDK_INT >= 24) {
ColorStateList trackStates = new ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{}
},
new int[]{
Color.GRAY,
Color.LTGRAY
}
);
switchInput.setTrackTintList(trackStates);
switchInput.setTrackTintMode(PorterDuff.Mode.OVERLAY);
}