遇到过很多次需要将 Activity 设置成 Dialog 样式的需求了,但都是网上百度到方法,直接粘贴上去完事儿,今天想来研究一下这个问题: themestyle 的区别


1. 综述

按照查到的资料来说,为 activity 或 application 设置 theme ,会将样式应用到 activity 或 application 的 所有元素 上。而 style 只能应用到 单个元素 上,并且 不能继承

由此我回想了一下,确实 theme 只出现在 activity 以及 application 中,而其它时候,我们用到的都是 style 这个属性。

2. theme 实例:将 activity 设置为 dialog 样式

  • 自定义一个 style
  • 在 activity 中的 theme 属性中引用该 style
  • 控制布局的大小

以上涉及到一个问题:设置窗口样式

  1. 什么是窗口

    所谓的窗体(Window)就是一个显示在手机屏幕上可视化视图的一片区域。在 Android 中窗口是一个抽象的概念,每一个 Activity 就对应着一个窗口,而所有的窗口都是由视图(View)来呈现,而我们知道View构成的一个树形结构的视图就组成了一个 Activity 的界面了。在 android 系统中窗口分为三个类型:

    • 应用窗口:所谓应用窗口指的 activity 对应的窗口。
    • 子窗口:所谓子窗口指的是必须依附在某个父窗口之上,如 dialog。
    • 系统窗口:所谓系统窗口指的是由系统进程创建,不依赖于任何应用或者不依附在任何父窗口之上,如 toast。

    总之,把窗口想象成一张白纸,layout 文件夹下的布局文件是我们要往上画的东西。

  2. 具体实现

    • 自定义 style

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <style name="dialogstyle">
      <!--设置窗口的背景-->
      <item name="android:windowBackground">@android:color/transparent</item>
      <!--设置窗口框为无-->
      <!--<item name="android:windowFrame">@null</item>-->
      <!--设置窗口无标题-->
      <item name="android:windowNoTitle">true</item>
      <!--设置窗口浮现在已有窗口之上-->
      <item name="android:windowIsFloating">true</item>
      <!--窗口是否半透明-->
      <item name="android:windowIsTranslucent">true</item>
      <!--设置窗口内容不覆盖-->
      <item name="android:windowContentOverlay">@null</item>
      <!--设置窗口动画,在这里使用让它继承系统的Animation.Dialog-->
      <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
      <!--背景是否模糊显示 目前没有弄懂这是干啥的--> /
      <item name="android:backgroundDimEnabled">true</item>
      </style>

      上面的代码是复制粘贴的,现在一个一个来讲

      • windowBackground: 就是窗口的背景啦,很好理解,设置成透明方便控制整体样式。当然有特殊需要的,可以引用 drawable 呀之类的

      • windowFrame: 这个就值得探讨了,因为我也没有得出结论来。说是控制窗口无边框,但我发现注释掉这一行后,样式并没有发生任何变化。由此我猜测,应用窗口本身就是没有边框的,如果我强行设置边框,比如:

        1
        <item name="android:windowFrame">@android:color/black</item>

        这个黑色会覆盖我整个窗口,遮盖住窗口中的所有元素。嗯所以还是注释掉吧这一行,没啥用

      • windowNoTitle: 有 true/false 两个值,默认 false,我应用主题没有 title,不设置为 true 程序会崩溃

      • windowIsFloating: 有 true/false 两个值,建议设置为 true 。否则就是在已有图案的画布上画东西,如果背景为透明的话,会看到重合的现象。而设置为 true, 就是在已有图案的画布上蒙一层画布再作画。应该能体会到区别吧 =-= 如果背景为透明的话,建议一定要设置为 true

      • windowIsTranslucent: 窗口是否半透明,这个也没有直观的看到效果

      • windowContentOverlay: 俗称闪屏页,就是程序启动时显示的画面,比如微博的闪屏页是广告(大多数都是广告)。如果没有设置,会有一段时间的白屏/黑屏。

      • windowAnimationStyle: 窗口进出动画。

      • backgrountDimEnabled: true : 背景是暗的, false : 背景是亮的。

      以上的属性分析应该有错,等时机成熟,去钻研一下 API。

    • 引用 style

      1
      2
      <activity android:name=".ImportActivity" 
      android:theme="@style/dialogStyle"/>
    • 控制布局大小(也就是想要展示出来的区域)

      1
      2
      3
      4
      5
      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="wrap_content">
      </LinearLayout>

      设置绘画区域高度为自适应、与窗口同宽。

3. style 实例:为单一元素自定义样式

  • 自定义一个 style
  • 在元素中通过 style 属性引用该 style
  1. 具体实现

    • 自定义 style

      1
      2
      3
      4
      5
      6
      7
      <!--textview 的基本样式-->
      <style name="tv_base_style">
      <item name="android:textColor">@color/white</item>
      <item name="android:textSize">23sp</item>
      <item name="android:layout_width">wrap_content</item>
      <item name="android:layout_height">wrap_content</item>
      </style>
    • 引用该 style

      1
      2
      <TextView
      style="@style/tv_base_style"/>

参考文档

  1. Android样式(style)和主题(theme)
  2. Android中使用Dialog风格弹出框的Activity
  3. Android创建窗口(一)创建应用窗口