在做新行程项目期间,遇到了很多关于UI布局的问题,这里总结一部分,都是一些小细节,希望能加深理解,以后少走弯路。
一 页面唤起后view创建完成的时间
Activity的生命周期为下图所示:
Activity在onCreate中使用setContentView()方法中载入xml布局,那么布局中的view是在何时完成创建的呢?在父布局中添加一个TextView,使用getLeft()、getRight()方法获取TextView在父布局中的左右边界的位置,打印出来可以看到
在onResume方法中获取的位置依然为0,按下home键后,将应用置为后台运行,可以看到
在onPause方法中打印出了位置,所以Activity中view创建完成的时间是在调用OnResume()方法返回之后,在此之前是无法获取view的位置信息的,fragment也是类似的,fragment的生命周期如图:
同样在布局中添加一个TextView,页面启动后打印TextView的位置,可以看到
在OnResume方法中也并没有打印出TextView得位置,按下home键,可以看到
打印出了TextView得位置,所以Fragment中view从创建完成到可见也是在OnResume()方法返回之后。那么如何才能知道activity已经完全加载,view已经可见了呢,可以根据OnWindowFocusChange()回调方法来判断。
OnWindowFocusChange()在OnResume()或者OnPause()方法调用完成之后被调用,可以保证activity已经完全加载,如图所示
背景图片会随着文字内容的变化动态调整大小而不会失真,在使用.9图片时候需要注意可操作区域的大小,每条边都要设置操作区域,如果设置.9图片的拉伸区域为:
那么在尖角上面的区域就是不可操作的区域,如图:
文本只存在于下方可操作区域内,上面的空间就无法使用了,正确的设置方法为:
保证可编辑区域的大小范围满足要求。
一 页面唤起后view创建完成的时间
Activity的生命周期为下图所示:
Activity在onCreate中使用setContentView()方法中载入xml布局,那么布局中的view是在何时完成创建的呢?在父布局中添加一个TextView,使用getLeft()、getRight()方法获取TextView在父布局中的左右边界的位置,打印出来可以看到
在onResume方法中获取的位置依然为0,按下home键后,将应用置为后台运行,可以看到
在onPause方法中打印出了位置,所以Activity中view创建完成的时间是在调用OnResume()方法返回之后,在此之前是无法获取view的位置信息的,fragment也是类似的,fragment的生命周期如图:
同样在布局中添加一个TextView,页面启动后打印TextView的位置,可以看到
在OnResume方法中也并没有打印出TextView得位置,按下home键,可以看到
打印出了TextView得位置,所以Fragment中view从创建完成到可见也是在OnResume()方法返回之后。那么如何才能知道activity已经完全加载,view已经可见了呢,可以根据OnWindowFocusChange()回调方法来判断。
OnWindowFocusChange()在OnResume()或者OnPause()方法调用完成之后被调用,可以保证activity已经完全加载,如图所示
二 复用View时避免之前View的属性的影响
在使用RecyclerView,ListView或者GridView时,为了节省内存,android系统将新创建的view直接复用上一个同类型的、当前已不可见的view,以RecyclerView为例,设置RecyclerView的item布局为一个ImageView加一个TextView,在adapter的OnBindViewHolder()中设置第一个item的字体颜色为红色,代码如下:
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String url = mUrlList.get(position);
Picasso.with(mContext).load(url).into(holder.mIvPic);
holder.mTvText.setText("这是第 " + position + "个");
if(position == 0){
holder.mTvText.setTextColor(Color.parseColor("#ff0000"));
}
}
运行效果如图所示:
咋看起来满足了要求,只有第一个item的字体标红了,但是上下滚动几次,使得别的view能够复用第一个view,可以看到
别的item也出现了字体被标红的效果,这是由于在view复用的时候,只是对特殊情况进行了处理,并没有对正常情况进行处理,简单来说就是只设置第一个位红色,没有设置非第一个为黑色,没有做到有if就有else,重写onBindViewHolder方法为:
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String url = mUrlList.get(position);
Picasso.with(mContext).load(url).into(holder.mIvPic);
holder.mTvText.setText("这是第 " + position + "个");
if(position == 0){
holder.mTvText.setTextColor(Color.parseColor("#ff0000"));
}else{
holder.mTvText.setTextColor(Color.parseColor("#000000"));
}
}
这样就不会出现非0个view字体标红的情况了,如图:
与此类似,当使用RecyclerView、ListView或者GridView时,要注意上一个view对之后view复用的影响,对于特殊属性的处理,要做到有if就要有else,避免属性不同的影响。
三 .9图片的可绘制区域
Android使用9patch处理图片以保证图片不会随着屏幕尺寸的变化而失真,如图:背景图片会随着文字内容的变化动态调整大小而不会失真,在使用.9图片时候需要注意可操作区域的大小,每条边都要设置操作区域,如果设置.9图片的拉伸区域为:
那么在尖角上面的区域就是不可操作的区域,如图:
文本只存在于下方可操作区域内,上面的空间就无法使用了,正确的设置方法为:
保证可编辑区域的大小范围满足要求。
总结
还有一些小细节,比如RelativeLayout使用wrap_content属性,如果其内部View使用alignParentBottom或者alignParentRight等需要依赖父布局位置时,RelativeLayout就会撑满全屏等,都是一些小细节,陆续还会总结,以便加深记忆,提高效率。
该文章来自于阿里巴巴技术协会(ATA)
作者:萧锁