【问题标题】:Change the Right Margin of a View Programmatically?以编程方式更改视图的右边距?
【发布时间】:2011-05-27 05:23:16
【问题描述】:

这个属性可以在Java代码中动态改变吗?

android:layout_marginRight

我有一个TextView,它必须动态地将其位置更改为向左一些像素。

如何以编程方式进行?

【问题讨论】:

    标签: android layout textview


    【解决方案1】:

    编辑:一种更通用的方法,不依赖于布局类型(除了它是支持边距的布局类型):

    public static void setMargins (View v, int l, int t, int r, int b) {
        if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
            p.setMargins(l, t, r, b);
            v.requestLayout();
        }
    }
    

    您应该查看TextView 的文档。基本上,您需要获取 TextView 的 LayoutParams 对象,并修改边距,然后将其设置回 TextView。假设它在 LinearLayout 中,请尝试以下操作:

    TextView tv = (TextView)findViewById(R.id.my_text_view);
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)tv.getLayoutParams();
    params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
    tv.setLayoutParams(params);
    

    我现在无法对其进行测试,所以我的投射可能会有所偏差,但需要修改 LayoutParams 以更改边距。

    注意

    不要忘记,如果你的 TextView 在里面,例如,一个 RelativeLayout,应该使用 RelativeLayout.LayoutParams 而不是 线性布局.LayoutParams

    【讨论】:

    • 只是为了详细说明您的答案,以防其他人正在寻找这个。如果您以编程方式创建 TextView,那么您还需要创建一个新的 LinearLayout.LayoutParams 对象,而不是尝试通过 .getLayoutParams();
    • 这很棒,而且它似乎以像素为单位设置边距。可以在dp中设置吗?
    • @KKendall:先convert your DP to PX
    • 根据您的注意:我有疑问。如果文本视图或按钮位于表格行内?那我应该用什么来代替Relative Layout,Table Layout呢?
    • 与注释相关,您可以将 tv.getLayoutParams() 转换为 ViewGroup.MarginLayoutParams。这样,只要实现边距,父级的布局就无关紧要
    【解决方案2】:

    使用 LayoutParams(如前所述)。但是要小心选择哪个 LayoutParams。根据https://stackoverflow.com/a/11971553/3184778“您需要使用与您正在处理的视图的父级相关的视图,而不是实际视图”

    例如,如果 TextView 在 TableRow 内,那么您需要使用 TableRow.LayoutParams 而不是 RelativeLayout 或 LinearLayout

    【讨论】:

    • 感谢您的澄清!
    • 你必须知道文本框的目的地才能设置边距,这真的很糟糕......你会认为会有一个独立于目的地的解决方案。
    【解决方案3】:

    使用此函数设置所有类型的边距

          public void setViewMargins(Context con, ViewGroup.LayoutParams params,      
           int left, int top , int right, int bottom, View view) {
    
        final float scale = con.getResources().getDisplayMetrics().density;
        // convert the DP into pixel
        int pixel_left = (int) (left * scale + 0.5f);
        int pixel_top = (int) (top * scale + 0.5f);
        int pixel_right = (int) (right * scale + 0.5f);
        int pixel_bottom = (int) (bottom * scale + 0.5f);
    
        ViewGroup.MarginLayoutParams s = (ViewGroup.MarginLayoutParams) params;
        s.setMargins(pixel_left, pixel_top, pixel_right, pixel_bottom);
    
        view.setLayoutParams(params);
    }
    

    【讨论】:

    • 为什么要增加 0.5f?
    • @behelit 我知道这已经晚了,但对于任何正在寻找的人来说......当你将浮点数转换为整数时,浮点数会循环。 0.0 -> 0.4 舍入为 0,而 0.5 -> 0.9 舍入为 1。这可能会导致最终整数不一致。为防止这种情况,添加 0.5 可确保所有舍入为 1。为什么?假设您的浮点数为 0.3:0.3 + 0.5 = 0.8,向上舍入为 1。假设您的浮点数为 0.8:0.8 + 0.5 = 1.3,向下舍入为 1。现在您可以安全地了解最终舍入(旁注:我们添加 0.5 而不是减去,以避免得到负 int)
    【解决方案4】:

    更新:Android KTX

    Core KTX module 为作为 Android 框架一部分的公共库提供扩展,androidx.core.view 就是其中之一。

    dependencies {
        implementation "androidx.core:core-ktx:{latest-version}"
    }
    

    以下扩展函数可以方便地处理边距:

    注意:都是MarginLayoutParams的扩展函数,所以 首先,您需要获取并转换您的视图的layoutParams

    val params = (myView.layoutParams as ViewGroup.MarginLayoutParams)
    

    设置ViewGroupMarginLayoutParams中所有轴的边距。 (尺寸必须以像素为单位,如果要使用 dp,请参阅最后一节)

    inline fun MarginLayoutParams.setMargins(@Px size: Int): Unit
    // E.g. 16px margins
    params.setMargins(16)
    

    更新ViewGroupViewGroup.MarginLayoutParams 中的边距。

    inline fun MarginLayoutParams.updateMargins(
        @Px left: Int = leftMargin, 
        @Px top: Int = topMargin, 
        @Px right: Int = rightMargin, 
        @Px bottom: Int = bottomMargin
    ): Unit
    // Example: 8px left margin 
    params.updateMargins(left = 8)
    

    更新ViewGroupMarginLayoutParams 中的相对边距(开始/结束而不是左/右)。

    inline fun MarginLayoutParams.updateMarginsRelative(
        @Px start: Int = marginStart, 
        @Px top: Int = topMargin, 
        @Px end: Int = marginEnd, 
        @Px bottom: Int = bottomMargin
    ): Unit
    // E.g: 8px start margin 
    params.updateMargins(start = 8)
    

    以下扩展属性可以方便地获取当前边距:

    inline val View.marginBottom: Int
    inline val View.marginEnd: Int
    inline val View.marginLeft: Int
    inline val View.marginRight: Int
    inline val View.marginStart: Int
    inline val View.marginTop: Int
    // E.g: get margin bottom
    val bottomPx = myView1.marginBottom
    
    • 使用dp 代替px

    如果您想使用dp(与密度无关的像素)而不是px,则需要先转换它们。您可以使用以下扩展属性轻松做到这一点:

    val Int.px: Int
        get() = (this * Resources.getSystem().displayMetrics.density).toInt()
    

    然后就可以调用之前的扩展函数如:

    params.updateMargins(start = 16.px, end = 16.px, top = 8.px, bottom = 8.px)
    val bottomDp = myView1.marginBottom.dp
    

    旧答案:

    在 Kotlin 中,您可以声明一个扩展函数,例如:

    fun View.setMargins(
        leftMarginDp: Int? = null,
        topMarginDp: Int? = null,
        rightMarginDp: Int? = null,
        bottomMarginDp: Int? = null
    ) {
        if (layoutParams is ViewGroup.MarginLayoutParams) {
            val params = layoutParams as ViewGroup.MarginLayoutParams
            leftMarginDp?.run { params.leftMargin = this.dpToPx(context) }
            topMarginDp?.run { params.topMargin = this.dpToPx(context) }
            rightMarginDp?.run { params.rightMargin = this.dpToPx(context) }
            bottomMarginDp?.run { params.bottomMargin = this.dpToPx(context) }
            requestLayout()
        }
    }
    
    fun Int.dpToPx(context: Context): Int {
        val metrics = context.resources.displayMetrics
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), metrics).toInt()
    }
    

    那么你可以这样称呼它:

    myView1.setMargins(8, 16, 34, 42)
    

    或者:

    myView2.setMargins(topMarginDp = 8) 
    

    【讨论】:

    • 第一个答案请添加完整的代码示例
    • 什么意思?都有例子
    • params varaibble 在代码中被遗漏了,但我在第一种情况下找到了它,而不是在其他情况下现在你的答案是完全描述性的
    猜你喜欢
    • 2017-03-17
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    相关资源
    最近更新 更多