LayoutParams理解和使用「建议收藏」

LayoutParams理解和使用「建议收藏」LayoutParams理解和使用

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

LayoutParams的理解

顾名思义,就是Layout Parameters :布局参数

例如

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Errol-King"
        android:textColor="#ff0000"/>

我们都知道layout_widthlayout_height这两个属性是为View指定宽高的。不过,为什么要加上layout_前缀修饰呢?其它的描述属性,如textColorbackground,都很正常。为什么不用width和height描述宽高呢?

LayoutParams,它说layout_width是它的属性而非View的,并且不只是针对这一个,而是所有以”layout_”开头的属性都与它有关。所以,它的东西当然要打上自己的标识”layout_”

既然layout_width这样的属性是LayoutParams定义的,那为何会出现在描述View的xml属性里呢?看下官方文档怎么说:

1、LayoutParams are used by views to tell their parents how they want to be laid out.
– LayoutParams是View用来告诉它的父控件如何放置自己的

2、The base LayoutParams class just describes how big the view wants to be for both width and height.
–基类LayoutParams(也就是ViewGroup.LayoutParams)仅仅描述了这个View想要的宽度和高度

3、There are subclasses of LayoutParams for different subclasses of
ViewGroup.
– 不同ViewGroup的继承类对应着不同的ViewGroup.LayoutParams的子类

更加直白的翻译:
1、textColorbackground这样的属性都是只与TextView自身有关的,无论这个TextView处于什么环境,这些属性都是不变的
layout_widthlayout_marginLeft这样的属性是与它的父控件息息相关的,是父控件通过LayoutParams提供这些”layout_”属性给孩子们用的;是父控件根据孩子们的要求(LayoutParams)来决定怎么测量,怎么安放孩子们的

2、基类LayoutParams是ViewGroup类里的一个静态内部类(看吧,这就证明了LayoutParams是与父控件直接相关的),它的功能很简单,只提供了width和height两个属性,对应于xml里的layout_widthlayout_height。所以,对任意系统提供的容器控件或者是自定义的ViewGroup,其chid view总是能写layout_widthlayout_height属性的

3、自从有了ViewGroup.LayoutParams后,我们就可以在自定义ViewGroup时,根据自己的逻辑实现自己的LayoutParams,为孩子们提供更多的布局属性。不用说,系统里提供给我们的容器控件辣么多,肯定也有很多LayoutParams的子类

LayoutParams 的作用是:子控件告诉父控件,自己要如何布局

ViewGroup.MarginLayoutParams

看名字我们也能猜到,它是用来提供margin属性的。

看看这个类里面的属性:

public static class MarginLayoutParams extends ViewGroup.LayoutParams {

        public int leftMargin;

        public int topMargin;

        public int rightMargin;

        public int bottomMargin;

        private int startMargin = DEFAULT_MARGIN_RELATIVE;

        private int endMargin = DEFAULT_MARGIN_RELATIVE;

        ...
    }    

前面4个属性是我们以前在布局文件里常用的,而后面的startMarginendMargin是为了支持RTL设计出来代替leftMarginrightMargin

一般情况下,View开始部分就是左边,但是有的语言目前为止还是按照从右往左的顺序来书写的,例如阿拉伯语。在Android 4.2系统之后,Google在Android中引入了RTL布局,更好的支持了从右往左文字布局的显示。为了更好的兼容RTL布局,google推荐使用MarginStartMarginEnd来替代MarginLeft和MarginRight`,这样应用可以在正常的屏幕和从右往左显示文字的屏幕上都保持一致的用户体验

关于RTL的文章请戳这里

在xml布局里,layout_margin属性的值会覆盖layout_marginLeftlayout_marginRight等属性的值。

常见的添加View的方式

Android动态添加View

LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
// 1.直接添加一个“裸”的TextView,不主动指定LayoutParams
TextView textView = new TextView(this);
textView.setText("宅在家的Errol_King");
textView.setTextColor(Color.RED);
parent.addView(textView);

// 2.先手动给TextView设定好LayoutParams,再添加
textView = new TextView(this);
textView.setText("来上班的Errol_King");
textView.setTextColor(Color.GREEN);
//300的单位是px
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(300,300);
textView.setLayoutParams(lp);
parent.addView(textView);
//上边两句可以简化为parent.addView(textView,lp);

// 3.在添加的时候传递一个创建好的LayoutParams
textView = new TextView(this);
textView.setText("玩游戏的Errol_King");
textView.setTextColor(Color.BLUE);
//这里是设置TextView的布局
LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,300);
parent.addView(textView, lp2);

上面代码展示的是3种往LinearLayout里动态添加TextView的方式,其中都涉及到了addView这个方法。我们来看看addView的几个重载方法:

//这3个方法都来自于基类ViewGroup

 public void addView(View child) { 
   
        addView(child, -1);
    }


public void addView(View child, int index) { 
   
        if (child == null) { 
   
            throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
        }
        LayoutParams params = child.getLayoutParams();
        if (params == null) { 
   
            params = generateDefaultLayoutParams();
            if (params == null) { 
   
                throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
            }
        }
        addView(child, index, params);
    }

public void addView(View child, LayoutParams params) { 
   
        addView(child, -1, params);
    }    

可以看出addView(View child)是调用了addView(View child, int index)方法的,在这个里面对child的LayoutParams做了判断,如果为null的话,则调用了generateDefaultLayoutParams方法为child生成一个默认的LayoutParams

让我们看看LinearLayout为我们这群懒人生成了怎样的默认LayoutParams

@Override
protected LayoutParams generateDefaultLayoutParams() { 
   
        if (mOrientation == HORIZONTAL) { 
   
            return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        } else if (mOrientation == VERTICAL) { 
   
            return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        }
        return null;
}

显然,LinearLayout是重写了基类ViewGroup里的generateDefaultLayoutParams方法的:如果布局是水平方向,则孩子们的宽高都是WRAP_CONTENT,而如果是垂直方向,高仍然是WRAP_CONTENT,但宽却变成了MATCH_PARENT。所以,这一点大家得注意,因为很有可能因为我们的懒,导致布局效果和我们理想中的不一样。因此呢,第1种添加View的方式是不推荐滴,像第2或第3种方式,添加的时候指定了LayoutParams,不仅明确,而且易修改

栗子1:动态修改布局

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/parent"
    >

    <TextView
        android:id="@+id/textView"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:text="Hello world"
        android:background="#000"
        android:textColor="#fff"/>

</LinearLayout>

效果
这里写图片描述

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

        textView = (TextView)findViewById(R.id.textView);

        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(textView.getLayoutParams());
        layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
        layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
        //设置margin值是px
        layoutParams.setMargins(20,20,20,20);
        layoutParams.gravity = Gravity.CENTER;

        textView.setLayoutParams(layoutParams);
    }

效果

LayoutParams理解和使用「建议收藏」

栗子2:RelativeLayout相对位置设置

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent">

<TextView
    android:id="@+id/textView"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:text="Hello world"
    android:background="#000"
    android:textColor="#fff"/>

</RelativeLayout>

效果

这里写图片描述

		textView = (TextView)findViewById(R.id.textView);

        RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
        lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
        lp.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE);
        textView.setLayoutParams(lp);

效果

LayoutParams理解和使用「建议收藏」

栗子3:动态增加一个布局

public class MainActivity extends Activity { 
   
    @Override
    protected void onCreate(Bundle savedInstanceState) { 
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LinearLayout parent = (LinearLayout)findViewById(R.id.parent);

        Button button = (Button) LayoutInflater.from(this).inflate(R.layout.view_button,null);
        button.setBackgroundResource(R.drawable.red_border);
        button.setText("确认收货");
        button.setTextColor(Color.parseColor("#ff0000"));
        
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,dpToPx(this,40));
        layoutParams.setMargins(dpToPx(this,5),dpToPx(this,5),0,0);
        
        button.setLayoutParams(layoutParams);

        parent.addView(button);
    }

    public static int dpToPx(Context context, float dpValue) { 
   
        if (dpValue <= 0) { 
   
            return 0;
        }
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

效果
这里写图片描述

你应该了解的

LayoutParams类也只是简单的描述了宽高

宽和高都可以设置成三种值:
1、一个确定的值
2、FILL_PARENT,即填满(和父容器一样大小)
3、WRAP_CONTENT,即包裹住组件就好

setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));

这一句话其实是子对父的,也就是父布局下的子控件要设置这句话,并且由于布局很多,也不同,虽然都继承至ViewGroup但是各个布局的局性和方法有很大的不同

如果子控件的父布局是一个TableRow,应该这样写才算准确:

setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.FILL_PARENT));

这表示这个子控件的父布局是一个TableRow , 这样的LayoutParams 太多,所以应明确指明

不同的布局容器应使用与之相对应的LayoutParams

不同的布局容器应使用与之相对应的LayoutParams,因为不同的布局容器有自己特殊的属性需要设置

例如:
LinearLayout.LayoutParams
LinearLayout.LayoutParams lp= new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

FrameLayout.LayoutParams
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

RelativeLayout.LayoutParams
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);

原文

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191048.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 什么是MVC三层架构?「建议收藏」

    什么是MVC三层架构?「建议收藏」1.1、什么是MVC MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。 是将业务逻辑、数据、显示分离的方法来组织代码。 MVC主要作用是降低了视图与业务逻辑间的双向偶合。 MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。 Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:ValueObj

  • dts展开为platform_device结构过程分析

    dts展开为platform_device结构过程分析dts节点展开为platform_device结构过程分析1.概述本文主要是记录学习Linux解析dts的代码分析,以便进行后续回顾。平台:ARMVexpress内核版本:linux-4.92.dts节点展开为platform_device结构过程分析自从ARM引入的dts之后,bsp驱动代码产生了非常之大的变化,像在linux-2.6.32这些版本的platform驱动中,会存在大…

  • eigen使用教程_kafka简单使用

    eigen使用教程_kafka简单使用Eigen是可以用来进行线性代数、矩阵、向量操作等运算的C++库,它里面包含了很多算法。它的License是MPL2。它支持多平台。Eigen采用源码的方式提供给用户使用,在使用时只需要包含Eigen的头文件即可进行使用。之所以采用这种方式,是因为Eigen采用模板方式实现,由于模板函数不支持分离编译,所以只能提供源码而不是动态库的方式供用户使用。矩阵的定义:E…

    2022年10月18日
  • 树莓派4B 安装opencv完整教程基于python3(各种错误解决)

    树莓派4B 安装opencv完整教程基于python3(各种错误解决)本人一直在做opencv的项目,需要入手一块树莓派来在移动端跑opencv,所以买了一块树莓派4B,然后安装上了系统,开启了曲折的opencv安装之旅。首先有幸看到子豪兄的视频,还是很好的,所以直接跟着它子豪兄教你在树莓派上安装OpenCV教程安装opencv,但是后来发现各种不可名状的错误,最后发现他的是基于树莓派3B+,环境是python3.5,但是树莓派4B的环境是python4B,所以不…

  • 36氪| 中国企服软件金榜-项目管理软件排名揭晓

    36氪| 中国企服软件金榜-项目管理软件排名揭晓36氪企服点评榜单,不看资本,不看厂商,不看专家,只看数据近日,由36氪企服点评主办的中国企服软件金榜-项目管理系列榜单发布,榜单根据产品「用户满意度」与「市场表现」两项关键指标,由36氪独创算法得出,排除了人为因素对预评分以及排序结果的影响。Worktile和PingCode从上百个项目管理类产品中脱颖而出,斩获多项荣誉:Worktile荣登中国企服软件金榜: 项目管理系列榜单总榜Top1 最佳易用性Top2 最佳满意度Top1 细分领域项目管理榜单-通用协.

  • OpenERP Web开发[通俗易懂]

    OpenERP Web开发[通俗易懂]声明:本文非原创,原始出处为http://blog.csdn.net/mackz/article/details/22581517分类:原始页面:Welcome to OpenERP Web Training  在7和8下测试均可。  1.相关库/框架  主要:jQuery(使用1.8.3,如果使用新版本,其他jQuery插件也要升级或修改)、Underscore、QW

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号