Piasy · 更新于 2018-11-28 11:00:42

Best Practices for User Interface

Designing for Multiple Screens

  • 支持不同屏幕尺寸
    • layout中尽量使用wrap_contentmatch_parent,而不是固定的数值
    • 资源文件可以定义不同的Qualifier,根据屏幕尺寸(dp值,最小宽高dp值,large等),dpi级别,屏幕朝向等等
    • Nine-patch Bitmaps

Adding the App Bar

  • 使用Toolbar,setSupportActionBar设置tool bar,getSupportActionBar可以返回一个ActionBar对象(尽管设置的是tool bar),可以对app bar进行相关操作
  • app bar的action通过option menu进行设置,响应在onOptionsItemSelected回调中
  • up navigation:在manifest中声明parent activity,同时设置getSupportActionBar().setDisplayHomeAsUpEnabled(true);;如此设置之后就无需在代码中进行响应操作了;
  • action view和action provider:例如search view

Showing Pop-Up Messages

  • Snackbar,和Toast类似,但是更符合material design
  • 自动消失,可以加入action button
  • 使用在CoordinatorLayout中,还能让其他View在其显示时自动上移,协同显示

Creating Custom Views

  • 设计良好的自定义view首先应该是一个设计良好的类,高效利用cpu和内存等
  • 且应该遵循安卓的标准
  • 提供xml属性,可以在layout中配置view
  • accessibility && compatibility
  • onDraw函数中进行自定义绘制
  • onSizeChanged函数中响应尺寸的变化,layout的变化
  • onLayout, onMeasure
  • 响应输入事件:点击、滑动、fling等,onTouchEvent
  • TouchEvent的信息比较原始,通常可以使用系统提供的帮助类提供的高级API:GestureDetector
  • fling事件的处理需要结合Scroller,动画等方式,以达到真实世界的物理运动效果
  • 优化view的效率
    • 减小循环被调用的函数的执行时间,例如onDraw;减少其中的内存分配;
    • 在初始化,或者动画开始前进行对象的创建,避免在动画过程中进行内存分配;
    • 减少invalidate()的调用,但是要注意,当view的内容发生变化需要更新时,必须要调用,否则不会生效;
    • 减少requestLayout()的调用,它可能会导致多次遍历整个view树;同时也应该使得布局扁平化,不要太深的嵌套;
    • 如果ui过于复杂,可以考虑自定义ViewGroup以对ui进行加速处理;这时ViewGroup的子view是满足特定条件的,可以减少measure, layout的必要;

Creating Backward-Compatible UIs

  • 通过抽象出接口,来定义UI的API,再根据不同的系统版本,选择不同的实现,以达到兼容的目的;
  • 新版系统直接proxy到新的系统API,旧的版本采取自定义实现方式;

Implementing Accessibility

...

Managing the System UI

  • 包括状态栏(顶部),导航栏(底部虚拟按键区域)
  • API 14+,让status bar可见性为gone,指定theme为@style/Theme.AppCompat.Light.NoActionBar.FullScreen或者@android:style/Theme.Holo.NoActionBar.Fullscreen

      <style name="Theme.AppCompat.Light.NoActionBar.FullScreen" parent="@style/Theme.AppCompat.Light">
          <item name="windowNoTitle">true</item>
          <item name="windowActionBar">false</item>
          <item name="android:windowFullscreen">true</item>
          <item name="android:windowContentOverlay">@null</item>
      </style>
  • API 14+,让navigation bar可见性为gone

      View decorView = getWindow().getDecorView();
      // Hide both the navigation bar and the status bar.
      // SYSTEM_UI_FLAG_FULLSCREEN is only available on Android 4.1 and higher, but as
      // a general rule, you should design your app to hide the status bar whenever you
      // hide the navigation bar.
      int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                  | View.SYSTEM_UI_FLAG_FULLSCREEN;
      decorView.setSystemUiVisibility(uiOptions);
  • 注意,上述方式有以下问题
    • 用户点击任何区域,都会导致navigation bar出现,且保持可见(属性被清除);
    • 一旦属性被清除,需要重新设置,使得navigation bar重新隐藏;
    • 所以需要decorView.setOnSystemUiVisibilityChangeListener,监听system ui可见性变化,在可见时,通过postDelayed,再次隐藏之;
  • API 19+,以后,引入了SYSTEM_UI_FLAG_IMMERSIVESYSTEM_UI_FLAG_IMMERSIVE_STICKY,前者同样存在上述问题;
  • 更完整的可以参考最新版AndroidStudio(2.0 preview 7)创建的FullscreenActivity模板;
  • 响应system ui可见性的变化

      View decorView = getWindow().getDecorView();
      decorView.setOnSystemUiVisibilityChangeListener
              (new View.OnSystemUiVisibilityChangeListener() {
          @Override
          public void onSystemUiVisibilityChange(int visibility) {
              // Note that system bars will only be "visible" if none of the
              // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
              if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                  // TODO: The system bars are visible. Make any desired
                  // adjustments to your UI, such as showing the action bar or
                  // other navigational controls.
              } else {
                  // TODO: The system bars are NOT visible. Make any desired
                  // adjustments to your UI, such as hiding the action bar or
                  // other navigational controls.
              }
          }
      });

Material Design for Developers

更多参见material design专题,包括:

  • material theme及其定制;
  • CardView, RecyclerView, item animation;
  • Custom shadows and view clipping;
  • Vector drawables, tint, palette;
  • Custom animations: ripple, reveal, activity transition, shared element transition, curved motion, Animate View State Changes, Animate Vector Drawables;

兼容性维护:

  • 各种backport;
  • Define Alternative Styles;
  • Provide Alternative Layouts;
  • Support Library;