getLayoutParams()方法和setLayoutParams()方法

本文详细解析了Android中的getLayoutParams()和setLayoutParams()方法,包括它们的作用、使用场景以及注意事项。强调getLayoutParams()需要父控件才能返回LayoutParams对象,而setLayoutParams()用于设置控件的布局参数。同时,解释了LayoutParams类的重要性,它是View向ViewGroup传递布局信息的载体,具有宽度、高度等属性设置选项。示例代码展示了在不同情况下正确使用这两个方法的方法。
部署运行你感兴趣的模型镜像

参考来源:http://blog.youkuaiyun.com/liuhaomatou/article/details/22899925#comments
1. getLayoutParams()和setLayoutParams()方法的解析
a. getLayoutParams():

/**
     * Get the LayoutParams associated with this view. All views should have
     * layout parameters. These supply parameters to the <i>parent</i> of this
     * view specifying how it should be arranged. There are many subclasses of
     * ViewGroup.LayoutParams, and these correspond to the different subclasses
     * of ViewGroup that are responsible for arranging their children.
     *
     * This method may return null if this View is not attached to a parent
     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
     * was not invoked successfully. When a View is attached to a parent
     * ViewGroup, this method must not return null.
     *
     * @return The LayoutParams associated with this view, or null if no
     *         parameters have been set yet
     */
  public ViewGroup.LayoutParams getLayoutParams() {
    return mLayoutParams;
}

大意就是getLayoutParams()方法的调用必须要有父控件。否则返回的就是null对象。该方法返回的是该控件的LayoutParams 对象。

b. setLayoutParams():
/**
     * Set the layout parameters associated with this view. These supply
     * parameters to the <i>parent</i> of this view specifying how it should be
     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
     * correspond to the different subclasses of ViewGroup that are responsible
     * for arranging their children.
     *
     * @param params The layout parameters for this view, cannot be null
     */
    public void setLayoutParams(ViewGroup.LayoutParams params) {
        if (params == null) {
            throw new NullPointerException("Layout parameters cannot be null");
        }
        mLayoutParams = params;
        resolveLayoutParams();
        if (mParent instanceof ViewGroup) {
            ((ViewGroup) mParent).onSetLayoutParams(this, params);
        }
        requestLayout();
    }

设置该控件的布局参数,也就是将修改好的参数信息重新赋值给该控件。

如下的示例代码:

 mImageViewTabline = (ImageView) findViewById(R.id.iv_tabline);
        //
        Display display = getWindow().getWindowManager().getDefaultDisplay();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        display.getMetrics(displayMetrics);
        //  获取到屏幕的的三分之一
        mScreen1_3 = displayMetrics.widthPixels / 3;
        // 获取到tabline控件的LayoutParams
        LayoutParams params = mImageViewTabline.getLayoutParams();
        // 设置tabline的宽度
        params.width = mScreen1_3;
        // 将修改好的的宽度设置给tabline控件
        mImageViewTabline.setLayoutParams(params);
  1. 关于setLayoutParams报错
      在继承BaseAdapter的时候,用getView返回View的时候,用代码控制布局,需要用到View.setLayoutParams,但是报错了,报的是类型转换错误,经过研究,发现,这里不能使用ViewGroup.LayoutParams而必须使用对应父View的LayoutParams类型。如:某View被LinearLayout包含,则该View的setLayoutParams参数类型必须是LinearLayout.LayoutParams。原因在于LinearLayout(或其他继承自ViewGroup的layout,如:RelativeLayout)在进行递归布局的时候,LinearLayout会获取子View的LayoutParams,并强制转换成LinearLayout.LayoutParams,如LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();

或者是如下定义:
LayoutParams lp = (LayoutParams) child.getLayoutParams();

以转换成内部类型LinearLayout.LayoutParams。

自己测试运行的时候报空指针,原因为child.getLayoutParams();这里没有获得到子控件所在的布局,查看代码发现parent.addView(child);应该写在上面,之后child才能getLayoutParams();

  1. LayoutParams类的解析
    LayoutParams继承于Android.View.ViewGroup.LayoutParams.
    LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息。假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉Layout用户期望的布局方式,也就是将一个认可的layoutParams传递进去。
    可以这样去形容LayoutParams,在象棋的棋盘上,每个棋子都占据一个位置,也就是每个棋子都有一个位置的信息,如这个棋子在4行4列,这里的“4行4列”就是棋子的LayoutParams。
    但LayoutParams类也只是简单的描述了宽高,宽和高都可以设置成三种值:
    1,一个确定的值;
    2,FILL_PARENT,即填满(和父容器一样大小);
    3,WRAP_CONTENT,即包裹住组件就好。
    LayoutParams类是用于child view(子视图) 向 parent view(父视图)传达自己的意愿的一个东西(孩子想变成什么样向其父亲说明)其实子视图父视图可以简单理解成一个LinearLayout 和 这个LinearLayout里边一个 TextView 的关系 。TextView 就是LinearLayout的子视图 child view 。需要注意的是LayoutParams只是ViewGroup的一个内部类,这里边这个也就是ViewGroup里边这个LayoutParams类是 base class 基类实际上每个不同的ViewGroup都有自己的LayoutParams子类。
    也就是说在LinearLayout类中有LayoutParams子类,在ViewGroup里面同样有LayoutParams子类。感兴趣的可以去翻看源码就知道了。

示例代码:

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                Log.e("tag", position + "," + positionOffset + "," + positionOffsetPixels);
                // 获取到父控件的参数
                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mImageViewTabline.getLayoutParams();
                // 0--->1
                if (mCurrentPageIndex == 0 && position == 0) {
                    layoutParams.leftMargin = (int) (positionOffset * mScreen1_3 + mCurrentPageIndex * mScreen1_3);
                } else if (mCurrentPageIndex == 1 && position == 0) {
                    //1---->0
                    layoutParams.leftMargin = (int) (mCurrentPageIndex * mScreen1_3 + (positionOffset - 1) * mScreen1_3);
                } else if (mCurrentPageIndex == 1 && position == 2) {
                    // 1--->2
                    layoutParams.leftMargin = (int) (mCurrentPageIndex * mScreen1_3 + positionOffset * mScreen1_3);
                } else if (mCurrentPageIndex == 2 && position == 1) {
                    // 2--->1
                    layoutParams.leftMargin = (int) (mCurrentPageIndex * mScreen1_3 + (positionOffset - 1) * mScreen1_3);
                }

                // 设置宽度给tabline
                mImageViewTabline.setLayoutParams(layoutParams);

            }

您可能感兴趣的与本文相关的镜像

GPT-SoVITS

GPT-SoVITS

AI应用

GPT-SoVITS 是一个开源的文本到语音(TTS)和语音转换模型,它结合了 GPT 的生成能力和 SoVITS 的语音转换技术。该项目以其强大的声音克隆能力而闻名,仅需少量语音样本(如5秒)即可实现高质量的即时语音合成,也可通过更长的音频(如1分钟)进行微调以获得更逼真的效果

<think>嗯,用户问的是Android开发中的setLayoutParamsrelayoutWindow的关系及用法。首先,我需要明确这两个方法各自的作用用途。 我记得setLayoutParams是用于更新View的布局参数,比如宽度、高度、边距等。当调用这个方法时,会触发View的重新布局,也就是requestLayout(),这样View会重新测量布局。这可能影响同级或父级视图的布局。例如,修改一个按钮的宽度,使用setLayoutParams来应用新的LayoutParams对象。 而relayoutWindow好像是更底层的方法,属于WindowManagerGlobal的静态方法。它直接与WindowManagerService通信,强制窗口立即重新布局。通常在需要即时更新窗口属性,比如窗口尺寸、位置或者可见性时使用。比如全屏切换或者动态调整窗口大小时可能会用到这个方法。 接下来,我需要理清它们的关系。两者都涉及布局的更新,但作用层次不同。setLayoutParams是View级别的,而relayoutWindow是窗口级别的。使用场景也不同,前者用于常规的视图布局调整,后者用于需要立即生效的窗口级变更。性能方面,relayoutWindow可能更消耗资源,因为它涉及系统服务的调用,应该谨慎使用。 然后,用户可能需要具体的使用示例,比如在什么情况下使用哪个方法。例如,调整一个View的位置或大小时用setLayoutParams,而需要立即调整窗口属性时用relayoutWindow。同时要注意,relayoutWindow需要正确的权限,并且可能需要处理跨进程通信的延迟或异常。 可能用户在实际开发中遇到了布局更新不及时的问题,或者在处理窗口属性时遇到困难。需要提醒他们正确选择方法,避免误用relayoutWindow导致性能问题。此外,还需要注意线程问题,relayoutWindow可能需要在主线程调用。 最后,确保回答结构清晰,分点说明区别、使用场景、注意事项,并给出代码示例帮助理解。同时检查是否有遗漏的重要点,比如是否需要修改WindowManager.LayoutParams,或者两者是否可以结合使用。</think>在Android开发中,`setLayoutParams``relayoutWindow`都是与界面布局相关的关键方法,但它们的应用场景底层机制有显著差异。以下是结构化解析: ### 一、核心区别 | 特性 | setLayoutParams | relayoutWindow | |---------------------|--------------------------------------|---------------------------------| | **作用层级** | View级别(ViewGroup.LayoutParams) | Window级别(WindowManager) | | **触发机制** | 请求异步布局更新(requestLayout) | 立即同步更新窗口属性 | | **性能消耗** | 相对较低 | 较高(涉及WMS跨进程通信) | | **典型应用场景** | 修改视图尺寸/边距/权重等 | 动态调整窗口尺寸/位置/透明度等 | ### 二、具体用法 #### 1. setLayoutParams ```java // 修改TextView的宽度边距 TextView tv = findViewById(R.id.my_text); ViewGroup.MarginLayoutParams params = (MarginLayoutParams) tv.getLayoutParams(); params.width = 200; // dp转px需处理屏幕密度 params.leftMargin = 30; tv.setLayoutParams(params); ``` *触发流程*:测量(onMeasure)→ 布局(onLayout)→ 绘制(onDraw)[^1] #### 2. relayoutWindow ```java // 调整窗口透明度 WindowManager.LayoutParams attrs = getWindow().getAttributes(); attrs.alpha = 0.5f; // 半透明效果 getWindow().setAttributes(attrs); // 强制立即生效 try { WindowManagerGlobal.getWindowManagerService() .relayoutWindow( getWindow().getDecorView().getWindowToken(), attrs.flags, attrs.x, attrs.y, attrs.width, attrs.height, attrs.alpha ); } catch (RemoteException e) { e.printStackTrace(); } ``` ### 三、联动场景 当需要同时修改视图窗口属性时: ```kotlin // 先更新视图布局 view.setLayoutParams(newParams) // 再调整窗口属性 window.attributes.apply { flags = FLAG_FULLSCREEN systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION } WindowManagerGlobal.relayoutWindow(...) ``` ### 四、注意事项 1. **线程安全**:`relayoutWindow`必须主线程调用 2. **性能优化**:避免高频调用relayoutWindow(>10次/秒可能触发ANR) 3. **兼容性**:relayoutWindow在Android 10+需要`SYSTEM_ALERT_WINDOW`权限 4. **参数有效性**:窗口尺寸参数受`minWidth/maxWidth`限制 ### 五、典型应用对比 | 需求 | 适用方法 | 原因 | |-------------------------|--------------------|----------------------------------------------------------------------| | 动态调整按钮间距 | setLayoutParams | 视图级布局变更 | | 实现沉浸式状态栏 | relayoutWindow | 需要修改窗口的SYSTEM_UI_FLAG | | 响应键盘弹出布局调整 | 两者结合 | 先调整视图布局,再修改窗口SOFT_INPUT_ADJUST_RESIZE | | 实现浮动窗口拖动效果 | relayoutWindow | 需要实时更新窗口位置(x/y坐标) | [^1]: 参考View.java源码中的`setLayoutParams()`实现,该方法最终会调用`requestLayout()`触发完整的视图树更新流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值