对于Android的布局来说常常提到的有 5个
可以自由设置相对已有ID名的元素的相对位置,比较适合使用比较复杂的不是行列规整的布局
分为纵列和横列,里面的元素都在该纵列或者行列里面,如果用于复杂的画面,则需要生成很多个LinearLayout来描画,开销比较大。
适用于多行多列的布局格式,里面的元素TableRow是LinerLayout的子类
里面每个元素都是层叠的,适合于切换里面元素用,里面设置位置是没有用的,只有gravity才有效。
只能通过坐标设置里面每个元素的位置,只是用于绝对位置固定的布局,对于现在大多数各种size的屏幕适应性不好。
setContentView()这个方法被调后,执行下面 将一个xml文件抽象成画面,
无论是android也好,还是flex等也罢,其实画面的生命周期包括 OnMeasure(测量)和OnLayout(布局)两个步骤的。
- 测量过程: 从XML根元素开始进行扫描,计算每个父控件的大小,向下层传递自己控件大小 (measure())
measure()返回后就是该空间包括子控件的大小已经 全部设置完毕。
- 布局过程:从XML根元素开始进行扫描,定位每个子视图,将子控件相对于父控件位置设置完毕。(layout())
可见当Layout的层级越多,解析,测量,布局,加载就会越慢,一个页面的生成速度也就越耗时。
所以一般提高Layout的加载速度减少耗时,核心思想就是减少层级关系,尽量少的使用类的实例。
- 不规则的嵌套页面使用ReletiveLayout,尽量少用LineLayout,可以减少层级
- 使用ViewStub延迟加载,只有必要的时候才加载
- <include/>重用标签,类似于C++中的#include
- 使用<merge/>标签,两个FrameLayout标签叠加 (当父控件是FrameLayout,多个子控件用include标签,并且子控件也是FrameLayout的结构时,可以叠加后, 这样子控件的内容就直接放入了父控件,少了一层。)
第一个RelativeLayout解释不用多说。先来解释一下ViewStub。ViewStub是不可视的(View.INVISIBLE),SIZE大小为0,可以在运行的时候inflate() 或者setVisibility()时再填充布局。但是注意3点:
1)ViewStub是一次性的,所谓一次性就是,当ViewStub的内容用inflate() 或者setVisibility()替换成相应布局后,ViewStub就立即被删除掉了,
此时再去findViewByID的时候是取不到该ViewStub的取到的是null。所以,ViewStub的这个View在onCreate使用后就不能再用。
2)ViewStub的size是0,如果该模块的布局根节点用RelativeLayout,当ViewStub下面还有控件A,位置设置成需要相对于ViewStub时候,可能就会出现问题。
因为XML是在setContentView时期解析的,那时候ViewStub还没有大小,控件A取到的位置是0,这个时候用的是系统默认布局,放在了整个根节点的左上。
解决方法是1)ViewStup和下面控件A用LineLayout.这样不用自己去计算位置比较省力。
2)自己根据ViewStub显示后去获取参数,设置控件A的布局(稍微比较繁琐)。
下面是1)的简单例子。画面一开始中间是不加载的,只有一个按钮,按钮按下就显示ViewStub所指向的布局。一个是TextView,一个是ImageView
activity_main.xml
<LinearLayout 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=".MainActivity" android:id="@+id/rl" android:orientation="vertical"> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text = "@string/show_Stub" android:id="@+id/inflate" /> <ViewStub android:id="@+id/text_stub" android:layout_width="fill_parent" android:layout_height="100dp" android:layout="@layout/text" android:inflatedId="@+id/text_view" /> <ViewStub android:id="@+id/image_stub" android:layout_width="fill_parent" android:layout_height="400dp" android:layout="@layout/imageview" android:inflatedId="@+id/image_view"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text = "@string/show_Stub" android:textSize="20dp" android:id="@+id/text_afterStub"/> </LinearLayout>
<?xml version ="1.0" encoding="utf-8"?> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:src="@drawable/ic_launcher" xmlns:android="http://schemas.android.com/apk/res/android"/>
<TextView android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="@string/app_name" xmlns:android="http://schemas.android.com/apk/res/android"/>
public class MainActivity extends Activity implements OnClickListener{ private View textStub; private View imageStub; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textStub = findViewById(R.id.text_stub); Button bt = (Button)findViewById(R.id.inflate); imageStub = findViewById(R.id.image_stub); bt.setOnClickListener(this); } private static boolean flag = true; @Override public void onClick(View v) { // TODO Auto-generated method stub flag = flag == true? false:true; if(flag) { textStub.setVisibility(View.VISIBLE); if(textStub.getParent() == null) { textStub = findViewById(R.id.text_view); } imageStub.setVisibility(View.GONE); } else { imageStub.setVisibility(View.VISIBLE); if(imageStub.getParent() == null) { imageStub.findViewById(R.id.image_view); } textStub.setVisibility(View.GONE); } } }