UI与布局
其它相关文章:
Android编程规范摘要1 (资源文件命名与使用)
Android编程规范摘要2 (基本组件)
Android编程规范摘要3 (UI与布局)
Android编程规范摘要4 (进程、线程与消息通信)
Android编程规范摘要5 (文件与数据库)
Android编程规范摘要6 (Bitmap、Drawable 与动画)
Android编程规范摘要7 (安全)
[强制] 布局中不得不使用ViewGroup 多重嵌套时,不要使用
LinearLayout
嵌套,改用RelativeLayout
,可以有效降低嵌套数。- 性能问题: 嵌套会增加view的measure耗时,层数越多,耗时越多。
- 消除冗余: 可以使用Hierarchy Viewer工具,可视化查看所有的view。
- 扁平结构: 不要加深嵌套,而是尽可能使所有的view保持扁平结果
在Activity 中显示对话框或弹出浮层时,尽量使用
DialogFragment
,而非Dialog/AlertDialog
,这样便于随Activity生命周期管理对话框/弹出浮层的生命周期。- 示例:
public void showPromptDialog(String text) { DialogFragment promptDialog = new DialogFragment() { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); View view = inflater.inflate(R.layout.fragment_prompt, container); return view; } }; promptDialog.show(getFragmentManager(), text); }
- 示例:
源文件统一采用UTF-8 的形式进行编码。
[强制] 禁止在非UI 线程进行View 相关操作。
文本和View的尺寸单位用dp。对于TextView,如果文字大小确定,推荐使用wrap_content参数,避免出现文字显示不全的适配问题。
- 文本尺寸在过去曾使用过sp。但sp不仅受屏幕密度影响,还受到系统设置里字体大小的影响。所以现在统一使用dp,可以保证UI的一致性和还原度
[强制] 禁止在设计布局时多次为子View和父View设置同样背景进而造成页面过度绘制,推荐将不需要显示的布局进行及时隐藏。
- 反例:
//给Rect每个区域绘制不同的颜色,但是在很多区域绘制过程明显重复。 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); mPaint.setColor(Color.GRAY); canvas.drawRect(0, 0, width, height, mPaint); mPaint.setColor(Color.CYAN); canvas.drawRect(0, height/4, width, height, mPaint); mPaint.setColor(Color.DKGRAY); canvas.drawRect(0, height/3, width, height, mPaint); mPaint.setColor(Color.LTGRAY); canvas.drawRect(0, height/2, width, height, mPaint); }
- 反例:
灵活使用布局,推荐merge、ViewStub 来优化布局,尽可能多的减少UI布局层级,推荐使用FrameLayout,
LinearLayout
、RelativeLayout
次之。在需要时刻刷新某一区域的组件时,建议通过以下方式避免引发全局layout 刷新:
- 设置固定的View 大小的宽高,如倒计时组件等;
- 调用View 的layout 方法修改位置,如弹幕组件等;
- 通过修改Canvas 位置并且调用
invalidate(int l, int t, int r, int b)
等方式限定刷新区域; - 通过设置一个是否允许
requestLayout
的变量,然后重写控件的requestlayout
、onSizeChanged
方法, 判断控件的大小没有改变的情况下, 当进入requestLayout
的时候,直接返回而不调用super
的requestLayout
方法。
不能在Activity 没有完全显示时显示
PopupWindow
和Dialog
。- Activity 创建时的生命周期:
onCreate()
->onStart()
->onResume()
->onAttachedToWindow()
->onWindowFocusChanged()
onAttachedToWindow()
: Activity 会与它的 Window 关联,UI才开始绘制,onWindowFocusChanged()
时,UI才变成可交互状态,可以提示用户使用。- 如果在 Window 未关联时就创建对话框,UI 可能显示异常。
- 推荐: 在
Activity#onAttachedToWindow()
之后(其实最好是Activity#onWindowFocusChanged()
之后)才创建对话框。
- Activity 创建时的生命周期:
尽量不要使用
AnimationDrawable
,它在初始化的时候就将所有图片加载到内存中,特别占内存,并且还不能释放,释放之后下次进入再次加载时会报错。- 当图片较大,或者图片较多时,要注意内存消耗,容易出现OOM。
[强制] 不能使用
ScrollView
包裹ListView
/GridView
/ExpandableListVIew
;因为这样会把ListView
的所有Item 都加载到内存中,要消耗巨大的内存和cpu去绘制。- 禁止:
ScrollView
中嵌套List
或RecyclerView
。 - 推荐使用
NestedScrollView
。
- 禁止:
[强制] 不要在Android 的
Application
对象中缓存数据。基础组件之间的数据共享, 请使用Intent
等机制,也可使用SharedPreferences
等数据持久化机制。使用
Toast
时,建议定义一个全局的Toast
对象,这样可以避免连续显示Toast
时不能取消上一次Toast 消息的情况。即使需要连续弹出Toast
,也应避免直接调用Toast#makeText
。[强制] 使用Adapter 的时候,如果你使用了
ViewHolder
做缓存,在getView()
的方法中无论这项convertView
的每个子控件是否需要设置属性,都需要为其显式设置属性。风险: 如果不显示设置属性,在滑动的过程中,因为adapter item 复用的原因,会出现内容的显示错乱。
正例
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder myViews; if (convertView == null) { myViews = new ViewHolder(); convertView = mInflater.inflate(R.layout.list_item, null); myViews.mUsername = (TextView)convertView.findViewById(R.id.username); convertView.setTag(myViews); } else { (ViewHolder)convertView.getTag(); } Info p = infoList.get(position); String dn = p.getDisplayName; myViews.mUsername.setText(StringUtils.isEmpty(dn) ? "" : dn); return convertView; }