カスタムviewgroupピット、サブviewのmarginを取得できません


今日、カスタムviewを使用するときは、親レイアウトがmarginを担当し、サブレイアウトがpaddingを担当していることしか知られていませんでした.カスタムviewgroupを使用している間もmarginということは考えていませんでしたが、今日突然やってみたいと思い、child.marginTopで取得した0を発見しました.この時、これはkotlinの拡張方法です.以下のように見てみましょう.
inline val View.marginTop: Int
    get() = (layoutParams as? MarginLayoutParams)?.topMargin ?: 0

その理由の多くは、取得したlayoutParamsがMarginLayoutParamsではなく、ネット上のブログを見てみると、layoutParamsがMarginLayoutParamsに強く移行してアクティブなmarginになったことをデフォルトで取得していたため、デバッグしてみると、取得したのはMarginLayoutParamsではないことが分かったので、ごろつきはソースコードを見るしかありません.xmlはinflateで解析して対応するviewを生成していると思いますので、LayoutInflateのinflateメソッドを見てみましょう
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
     
        View view = tryInflatePrecompiled(resource, res, root, attachToRoot);
        if (view != null) {
     
            return view;
        }
    }

xmlを解析してこのviewを取得するtryInflatePrecompiledメソッドが呼び出され、対応するlayoutParamsを生成するメソッドがviewに追加されていることがわかります.
ViewGroup.LayoutParams params = root.generateLayoutParams(attrs);
if (attachToRoot) {
     
     root.addView(view, params);
} else {
     
     view.setLayoutParams(params);
}

このattachToRootパラメータもよく知られています.親レイアウトに追加するか、レイアウトパラメータのみを適用するかです.また、このgenerateLayoutParamsメソッドではデフォルトのlayoutParamsパラメータしか生成されませんので、カスタムviewgroupはこのメソッドを書き換える必要があります.そうしないとmarginは使用できません.
public LayoutParams generateLayoutParams(AttributeSet attrs) {
     
    return new LayoutParams(getContext(), attrs);
}

したがって,この方法を直接書き換えてMarginLayoutParamsに戻るのが一般的であり,MarginLayoutParamsクラスでは受信したattrsを解析してmarginを取得する過程も見られる.
またviewgroupでondrawを使用して必要なインタフェースを描画する場合は、初期化関数にsetWillNotDraw(false)を設定する必要があります.そうしないとonDrawメソッドは呼び出されません.