• Android 通过Java代码生成创建界面。动态生成View,动态设置View属性。addRules详解


    废话不多说,本文将会层层深入给大家讲解如何动态的生成一个完整的界面。

    本文内容:

    1. Java代码中动态生成View
    2. Java代码中动态设置View的位置,以及其他的属性
    3. LayoutParams详解

    一、Java代码中动态的生成View

    我们以创建一个Button为例子。 
    1、首先我们在onCreate方法中创建一个Button实例:

    Button button=new Button(this);        
    • 1

    2、创建了Button实例下面我们就要指定它在哪个界面中显示: 
    首先第一步找到我们要显示的界面: 
    首先把setContentView()删掉(后文会讲)。 
    有两种方法:

    • 使用LayoutInflate
    • 使用findViewById

    1)LayoutInflate使用来找到一个布局文件:

          ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(this).inflate(R.layout.activity_main, null);
    • 1

    返回的是布局文件的最外层的View容器, 
    贴一下布局文件中的XML代码

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.miko.zd.dynamicview.MainActivity"
        android:id="@+id/relative">
    
    </RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这里LayoutInflate返回的就是最外层的RelativeLayout。RelativeLayout继承于ViewGroup因此完全没有问题。 
    2)通过FindViewByID返回最外层的View 
    第二种方法以第一种一致都是返回最外层的RelativeLayout:

            View viewGroup2 = findViewById(R.id.relative);
    • 1

    3、下一步就是要把我们的Button添加到RelativeLayout中了 
    使用ViewGroup的addView方法:

     viewGroup.addView(button);
    • 1

    运行代码,你会发现界面中什么都没有,为什么呢? 
    前文中说过删除setContentView()这个方法,setContenView可以理解为,为Activity绑定一个显示的的布局,我们只是找到了ViewGroup,并且添加了Button,但是没有绑定Activity,因此这里添加一句setContentView(viewGroup);你可能会说,我一开始不删除这一句,不可以么? 
    findViewById可以,setContentView()一旦调用,layout就会立刻显示UI,而后的findViewById,找到RelativeLayout实际上已经加载出来了,添加Button,可以理解为显示出UI后动态的添加View;而inflate只会把Layout形成一个以view类实现成的对象,有需要时再用setContentView(view)显示出来。 
    运行结果: 
    这里写图片描述 
    可以看到,相当原始的界面,下一步我们就要设置Button的位置以及相关属性了

    二、Java代码中动态设置View的位置,以及其他的属性

    1、首先我们为我们的Button设置一个背景,以及文字:

    button.setBackgroundColor(Color.RED);
    button.setText("Hello World");
    • 1
    • 2

    这里写图片描述 
    2、我们下一步想给Button设置长宽: 
    你可能会想button会有setHeight,setWidth方法,确实有,而且你可以实现设置长宽,但是如果你要设置Match_parent,Wrap_content,怎么实现呢?这时候我们就要使用LayoutParam方法了。 
    首先创建一个Layoutparams实例:

    RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(100,100);        
    • 1

    不同的布局对应着不同的LayoutParams,我们这里是RelativeLayout所以当然是R.layoutParam这里的两个参数是Button的宽以及高,注意这里的100代表着100px,使用dp可以参照我之前的博客 
    dp转px

    那么上文中的MATCH 以及WRAP怎么实现呢?

    RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    • 1

    运行结果:这里写图片描述 
    为什么没有效果呢,因为定义了LayoutParam但是没有指定哪一个View因此还需要添加一句

            button.setLayoutParams(params);
    • 1

    这里写图片描述 
    没有任何问题。 
    3、设置位置信息 
    我们想要使Button居中显示,怎么实现呢? 
    还是使用LayoutParams,使用他的addRules方法:

            params.addRule(RelativeLayout.CENTER_IN_PARENT);
    • 1

    这里写图片描述 
    addRules有两个方法:

    • addRule(int verb)
    • addRule(int verb, int anchor) 
      verb我们很好理解,就是各种规定位置的参数,anchor代表什么呢? 
      我们看源码注释: 
      The id of another view to use as an anchor, 
      * or a boolean value (represented as {@link RelativeLayout#TRUE} 
      * for true or 0 for false). For verbs that don’t refer to another sibling 
      * (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1. 
      实际上verb参数可以分为两类,一种是不要任何相对view的,比如ALIGN_WITH_PARENT_BOTTOM这种的参数,另一种需要相对view的参数,例如above,right_of等等,需要一个view来表示位置的参数,这个时候就需要用到anchor,anchor代表的是相对view的id。 
      下面我们再创建一个Button:
    ViewGroup viewGroup2 = (ViewGroup) viewGroup.findViewById(R.id.relative);
    
            Button button = new Button(this);
            RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.addRule(RelativeLayout.CENTER_IN_PARENT);
            button.setLayoutParams(params);
            button.setBackgroundColor(Color.RED);
            button.setText("Hello World");
            button.setId(100);
    
            Button button1=new Button(this);
            RelativeLayout.LayoutParams params1=new RelativeLayout.LayoutParams(200,200);
            params1.addRule(RelativeLayout.BELOW,100);
            button1.setLayoutParams(params1);
            button1.setBackgroundColor(Color.RED);
            button1.setText("Hello World");
    
            viewGroup2.addView(button);
            viewGroup2.addView(button1);
            setContentView(viewGroup);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    注意我们要先给第一个button一个id,因为是动态创建的所以使用setId方法,设id为100, params1.addRule(RelativeLayout.BELOW,100);核心代码,意思是将button1设置在id为100的view的下方。 
    运行结果: 
    这里写图片描述

    四、后记

    上文我为大家详细解析了View的动态创建,以及动态的添加属性,有几点需要注意的: 
    1、上文中的布局都是用的RelativeLayout,实际上你会发现只有RelativeLayout.layoutParam具有addRules方法,这其实是与XML中相对应的,你在LinearLayout中无法使用Right_of等等相对布局的属性,这些都是相通的。 实际上我认为在动态生成界面的几个布局中RelativeLayout是最简单也是最准确的。 
    2、为什么要使用动态生成界面?我想在编程中使用XML是无可厚非的,但是App的大趋势是动态化来减少版本更替,这就涉及到一个不要写死的问题,国内已经有很多尝试,即通过服务器动态生成界面。

  • 相关阅读:
    C# 向共享文件夹上传及下载文件
    Generate the Jobs script from msdb Database
    用水晶报表做条码打印
    多语言系统的实现
    用DataBaseMail发图片并茂的邮件
    浅析WINFORM工具条的重用实现
    具有代表性的财务报表--应收帐
    C#实现Combobox自动匹配字符
    动态列报表
    真正通用的SQL分页存储过程
  • 原文地址:https://www.cnblogs.com/wangfeng520/p/5741822.html
Copyright © 2020-2023  润新知