Lollipop以降に追加されたLayerDrawable#setTintList()ですが呼び出しても機能しません。
サンプル

原因
AOSPのソースを追ってみた所、LayerDrawable#isStateful()が古い結果をキャッシュし続けていてViewがDrawable#setState()を呼ばないのが原因のようです。
LayerDrawable#setTintList()の実装にキャッシュを無効化するコードが入ってないのでStatefulなはずなのにisStateful()がfalseを返してしまいます。
public void setTintList(ColorStateList tint) {
final ChildDrawable[] array = mLayerState.mChildren;
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final Drawable dr = array[i].mDrawable;
if (dr != null) {
dr.setTintList(tint);
}
}
// ← Statefulキャッシュを無効化してない
}
public boolean isStateful() {
return mLayerState.isStateful();
}
static class LayerState extends ConstantState {
public final boolean isStateful() {
if (mHaveIsStateful) { // ← こいつがキャッシュを保持し続ける
return mIsStateful;
}
final ChildDrawable[] array = mChildren;
final int N = mNum;
boolean isStateful = false;
for (int i = 0; i < N; i++) {
final Drawable dr = array[i].mDrawable;
if (dr != null && dr.isStateful()) {
isStateful = true;
break;
}
}
mIsStateful = isStateful;
mHaveIsStateful = true;
return isStateful;
}
}
if (mBackground.isStateful()) {
mBackground.setState(getDrawableState()); // ← isStateful()がtrueじゃない限りDrawable#setState()を呼んでくれない
}
回避方法
statefulキャッシュを無効化するにはLayerDrawable.LayerState#invalidateCache()を呼べばいいのですがそれを呼んでいるはLayerDrawable#setDrawable()とLayerDrawable#setDrawableByLayerId()です。
なのでsetTintList()を呼ぶ直前に上記のAPIを呼べばisStateful()は正しい結果を返して問題は解決します。
いちいち書くのは面倒なので簡単なUtilityクラスを用意しました。ソースにも書いてますがlayerの最初のitemにandroid:idの設定が必要になります。
public class LayerDrawableUtil {
public static void invalidateCache(Drawable d) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
if (!(d instanceof LayerDrawable)) return;
LayerDrawable ld = (LayerDrawable) d;
int count = ld.getNumberOfLayers();
if (count == 0) return;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// TODO first layer item needs to be set android:id
int id = ld.getId(0);
Drawable d0 = ld.findDrawableByLayerId(id);
ld.setDrawableByLayerId(id, d0);
} else {
Drawable d0 = ld.getDrawable(0);
ld.setDrawable(0, d0);
}
}
}
これを下のように使います。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Not Worked
Button button1 = (Button) findViewById(R.id.button1);
ViewCompat.setBackgroundTintList(button1, ContextCompat.getColorStateList(this, R.color.tint));
// Worked
Button button2 = (Button) findViewById(R.id.button2);
LayerDrawableUtil.invalidateCache(button2.getBackground());
ViewCompat.setBackgroundTintList(button2, ContextCompat.getColorStateList(this, R.color.tint));
}