存储分配的 ViewGroup.MarginLayoutParams 并在任意时刻修改它们

Storing assigned ViewGroup.MarginLayoutParams and modifying them at arbitrary moments

我需要根据 View 的某些内部状态修改自定义 ViewViewGroup.MarginLayoutParams

任务看起来像这样:

  1. View 的初始化期间设置一些 ViewGroup.MarginLayoutParams,同时保存它们以跟踪通过 View 的布局属性设置的内容(layout_marginTop, 等等).
  2. 在未来需要的时刻,使用存储值或其他一些值更改 ViewGroup.MarginLayoutParams

因此,我有两个问题:

  1. 通过布局属性设置的 ViewGroup.MarginLayoutParams 保存的正确位置是什么?

无法在 View 的构造函数中执行此操作,因为父 ViewGroup 尚未分配它。 onAttachedToWindow() 是正确的地方吗?

  1. onMeasure()是根据需要调整ViewGroup.MarginLayoutParams的正确位置吗?

像这样:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)getLayoutParams();
    params.topMargin = ...;
    setLayoutParams(params);

    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

由于在上面的代码中我们在 onMeasure() 中调用了 setLayoutParams() (当当前布局传递正在进行时),它会导致第二次布局传递吗?

您可以只保留对您正在使用的 ViewGroup 的引用,并根据需要调用 getLayoutParams。您需要使 params 变量成为 ViewGroup 的更具体实例 - 您可以将其实例化为

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) view.getLayoutParams();

然后,您可以调用您选择的

params.setMarginStart(int);
params.setMarginEnd(int);
params.setMargins(int, int, int, int);

设置边距。请注意,您根本不需要调用 setLayoutParams() 来应用更改。 params 变量和 view.getLayoutParams() 引用同一个对象,因此您对其中一个所做的任何更改都将应用于另一个。

完整的代码示例如下所示:

public final class MyActivity extends AppCompatActivity {

    RelativeLayout parent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        parent = (RelativeLayout) findViewById(R.id.parent);
    }

    private void setParentMargin(int left, int top, int right, int bottom) {
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) parent.getLayoutParams();
        params.setMargins(left, top, right, bottom);
        params.setMarginStart(left);
        params.setMarginEnd(right);
    }

}

只要您在 onCreate 之后调用该方法就可以了。

第二个问题的答案取决于触发保证金变化的事件。如果是在 activity 重新创建时,您可以在 onResume 中执行(因为这保证在 onCreate 之后发生)。您也可以从 onClickListener 或接口回调中调用它。因此,您不一定必须在 onMeasure.

中设置边距