正如@MartinCazares 指出的那样,问题在于布局参数在构造函数方法中不可用,并且将在视图膨胀期间被覆盖。但是,最好设置setLayoutParams()
在 View 膨胀期间将调用的边距,而不是 in onLayout()
。后者应该设置视图子项的布局,而不是更改视图本身的布局。因此,在我的 Android 12 上更改布局参数会导致屏幕闪烁。
我的解决方案:
private boolean hasLeftMargin = false;
private boolean hasRightMargin = false;
private boolean hasTopMargin = false;
private boolean hasBottomMargin = false;
public MyView(@NonNull Context context, @Nullable AttributeSet attrs) {
// Receive styled attributes
TypedArray arr = context.obtainStyledAttributes(attrs, new int[] {
android.R.attr.layout_margin,
android.R.attr.layout_marginLeft, android.R.attr.layout_marginTop,
android.R.attr.layout_marginRight, android.R.attr.layout_marginBottom,
android.R.attr.layout_marginStart, android.R.attr.layout_marginEnd});
// Check whether margin are assigned in xml (by index of int array above)
hasLeftMargin = arr.hasValue(0) || arr.hasValue(1) || arr.hasValue(5);
hasRightMargin = arr.hasValue(0) || arr.hasValue(3) || arr.hasValue(6);
hasTopMargin = arr.hasValue(0) || arr.hasValue(2);
hasBottomMargin = arr.hasValue(0) || arr.hasValue(4);
arr.recycle();
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params instanceof MarginLayoutParams) {
MarginLayoutParams p = (MarginLayoutParams) params;
if (!hasLeftMargin && p.leftMargin <= 0) p.leftMargin = sideMargin;
if (!hasRightMargin && p.rightMargin <= 0) p.rightMargin = sideMargin;
if (!hasTopMargin && p.topMargin <= 0) p.topMargin = verticalMargin;
if (!hasBottomMargin && p.bottomMargin <= 0) p.bottomMargin = verticalMargin;
}
super.setLayoutParams(params);
}