Android编程规范摘要3 (UI与布局)

本文提供了Android UI设计和布局优化的实用指南,包括减少视图嵌套、使用DialogFragment、编码规范、避免过度绘制等技巧,帮助开发者提高应用性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UI与布局


其它相关文章:
Android编程规范摘要1 (资源文件命名与使用)
Android编程规范摘要2 (基本组件)
Android编程规范摘要3 (UI与布局)
Android编程规范摘要4 (进程、线程与消息通信)
Android编程规范摘要5 (文件与数据库)
Android编程规范摘要6 (Bitmap、Drawable 与动画)
Android编程规范摘要7 (安全)


  1. [强制] 布局中不得不使用ViewGroup 多重嵌套时,不要使用LinearLayout 嵌套,改用RelativeLayout,可以有效降低嵌套数。

    • 性能问题: 嵌套会增加view的measure耗时,层数越多,耗时越多。
    • 消除冗余: 可以使用Hierarchy Viewer工具,可视化查看所有的view。
    • 扁平结构: 不要加深嵌套,而是尽可能使所有的view保持扁平结果
  2. 在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);
      }
  3. 源文件统一采用UTF-8 的形式进行编码。

  4. [强制] 禁止在非UI 线程进行View 相关操作。

  5. 文本和View的尺寸单位用dp。对于TextView,如果文字大小确定,推荐使用wrap_content参数,避免出现文字显示不全的适配问题。

    • 文本尺寸在过去曾使用过sp。但sp不仅受屏幕密度影响,还受到系统设置里字体大小的影响。所以现在统一使用dp,可以保证UI的一致性和还原度
  6. [强制] 禁止在设计布局时多次为子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);
      }
  7. 灵活使用布局,推荐merge、ViewStub 来优化布局,尽可能多的减少UI布局层级,推荐使用FrameLayout,LinearLayoutRelativeLayout次之。

  8. 在需要时刻刷新某一区域的组件时,建议通过以下方式避免引发全局layout 刷新:

    1. 设置固定的View 大小的宽高,如倒计时组件等;
    2. 调用View 的layout 方法修改位置,如弹幕组件等;
    3. 通过修改Canvas 位置并且调用invalidate(int l, int t, int r, int b)等方式限定刷新区域;
    4. 通过设置一个是否允许requestLayout 的变量,然后重写控件的requestlayoutonSizeChanged 方法, 判断控件的大小没有改变的情况下, 当进入requestLayout 的时候,直接返回而不调用superrequestLayout 方法。
  9. 不能在Activity 没有完全显示时显示PopupWindowDialog

    • Activity 创建时的生命周期:onCreate() -> onStart() -> onResume() -> onAttachedToWindow() -> onWindowFocusChanged()
    • onAttachedToWindow() : Activity 会与它的 Window 关联,UI才开始绘制, onWindowFocusChanged()时,UI才变成可交互状态,可以提示用户使用。
    • 如果在 Window 未关联时就创建对话框,UI 可能显示异常。
    • 推荐: 在 Activity#onAttachedToWindow()之后(其实最好是Activity#onWindowFocusChanged() 之后)才创建对话框。
  10. 尽量不要使用AnimationDrawable,它在初始化的时候就将所有图片加载到内存中,特别占内存,并且还不能释放,释放之后下次进入再次加载时会报错。

    • 当图片较大,或者图片较多时,要注意内存消耗,容易出现OOM。
  11. [强制] 不能使用ScrollView 包裹ListView/GridView/ExpandableListVIew;因为这样会把ListView 的所有Item 都加载到内存中,要消耗巨大的内存和cpu去绘制。

    • 禁止: ScrollView 中嵌套ListRecyclerView
    • 推荐使用NestedScrollView
  12. [强制] 不要在Android 的Application对象中缓存数据。基础组件之间的数据共享, 请使用Intent 等机制,也可使用SharedPreferences 等数据持久化机制。

  13. 使用Toast 时,建议定义一个全局的Toast 对象,这样可以避免连续显示Toast 时不能取消上一次Toast 消息的情况。即使需要连续弹出Toast,也应避免直接调用Toast#makeText

  14. [强制] 使用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;
      }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值