Android 下style和theme的用法

  Android中的style可以被多个界面共用,所以它适合为应用做一些基础的外观设置,可以使应用的外观既统一又容易修改。


style的用法为:

1.在values文件夹下新建一个style.xml文件


2.在style.xml文件中来设置android各个组件的属性。style节点有三个属性值,分别是

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

    <style name="content_demo">
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:textColor">#ff2376</item>
         <item name="android:textSize">30sp</item>
        <item name="android:background">#448811</item>

    </style>

    <style name="content_demo_child" parent="content_demo">
        <item name="android:textColor">#000000</item>
    </style>
</resources>
name   item 和 parent.

name属性来设置style的名称;

item属性来设置Android组建的属性;

parent属性来设置style之间的继承关系,也就是说一个style可以完全得到另一个style的全部设置。

并且子style可以复写父style的属性。


3.在layout.xml中,给需要使用样式的组建引入所需的style即可。

<?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="match_parent"
    android:orientation="vertical"
    >
<TextView
    style="@style/content_demo"
    android:text="我是第一个"
    />
    <TextView
        style="@style/content_demo"
        android:text="我是第二个"
        />
    <TextView
        style="@style/content_demo"
        android:text="我是第三个"
        /><TextView
    style="@style/content_demo_child"
    android:text="我是第四个"
    />

</LinearLayout>

theme和style没有什么区别,一个使用上比较大的区别就是,style主要是用来修饰Android的View的,而theme则主要是用来修饰Android的activity的。

如果想让某个主题修饰整个应用中所有的activity,只要把该theme设置到AndroidManifest.xml文件中的application节点下即可。



<think>根据用户的问题,用户遇到了在Android中使用Theme.NoDisplay主题导致报错的问题,并希望实现无Activity启动应用。结合引用内容,我们可以总结以下几点关键信息: 1. **引用[1]指出**:使用NoDisplay主题的Activity在6.0手机上正常resume时会出现ANR,因为Activity启动了但窗口无法显示,系统等待超过5秒导致ANR。Google建议使用`Theme.Translucent.NoTitleBar`替代,或者让Activity完全透明。 2. **引用[2]指出**:设置主题时,如果使用`android:theme="@android:style/Theme.Dialog"`可能导致报错。解决方法是将Activity的基类从`AppCompatActivity`改为`Activity`,但这不是最佳实践,因为会失去兼容库的特性。 3. **引用[4]指出**:使用Theme.NoDisplay会导致Activity创建延迟,虽然生命周期方法很快被调用,但实际可见需要几秒钟,这不符合无界面快速启动的需求。 4. **引用[5]给出示例**:使用`Theme.NoDisplay`主题的Activity通常用于处理隐式Intent(如Deep Link),并且不显示界面,例如在Manifest中配置一个透明的Activity来处理路由。 用户的需求是避免报错并正确实现无Activity启动应用。结合之前的回答(创建无界面后台服务),这里需要解决的是如何正确启动一个无界面的Activity来启动服务,或者完全避免使用Activity。 ### 解决方案: 1. **避免使用Theme.NoDisplay**:因为它可能导致ANR或延迟问题(引用[1][4])。 2. **使用透明主题替代**:`Theme.Translucent.NoTitleBar`可以让Activity完全透明,从而无界面显示,同时避免ANR问题。 3. **立即启动服务并关闭Activity**:在Activity的`onCreate`中启动服务后立即调用`finish()`关闭Activity,这样用户不会看到任何界面。 ### 具体实现步骤: #### 1. 修改Activity的主题为透明主题 在`AndroidManifest.xml`中,将启动Activity的主题设置为透明: ```xml <activity android:name=".MainActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" <!-- 关键:使用透明主题 --> android:exported="true" android:excludeFromRecents="true"> <!-- 不在最近任务列表显示 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ``` #### 2. 在Activity中立即启动服务并关闭 ```java public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 注意:不要设置任何布局(setContentView) // 启动后台服务 Intent serviceIntent = new Intent(this, BackgroundService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent); } else { startService(serviceIntent); } // 立即结束Activity,避免界面残留 finish(); } } ``` #### 3. 服务实现(同之前) 服务类`BackgroundService`的实现保持不变,包括创建前台通知等。 ### 为什么这样能解决问题? - **避免ANR**:使用透明主题(`Theme.Translucent.NoTitleBar`)不会阻塞主线程,因为系统知道这个Activity是透明的,不会等待界面渲染。 - **无界面效果**:Activity启动后立即启动服务并关闭,用户不会看到任何界面,达到无界面启动应用的效果。 - **符合启动要求**:在Android 8.0+上使用`startForegroundService`,并在服务中5秒内调用`startForeground`显示通知。 ### 注意事项: 1. **不要调用setContentView**:在透明Activity中不要设置任何布局,否则会显示一个透明界面(虽然看不到内容,但会占用窗口)。 2. **立即调用finish**:确保在`onCreate`中启动服务后立即调用`finish()`,避免Activity留在后台。 3. **排除最近任务列表**:在Manifest中设置`android:excludeFromRecents="true"`,避免用户从最近任务中看到这个Activity。 ### 替代方案:完全无Activity启动 在Android 3.1+以后,应用安装后处于“停止状态”,必须通过显式Intent(如点击Launcher图标)启动一次才能接收广播等。因此,完全无Activity启动应用通常不可行,除非是系统应用。所以,使用一个透明的启动Activity来初始化服务是最佳实践。 ### 总结 通过使用透明主题(`Theme.Translucent.NoTitleBar`)替代`Theme.NoDisplay`,并在启动服务后立即结束Activity,可以避免ANR延迟问题,实现无界面启动后台服务。 --- ### §§相关问题§§ 1. **如何实现设备重启后自动启动后台服务?** (通过监听`BOOT_COMPLETED`广播并重新启动服务) 2. **Android 12+ 的前台服务启动权限如何声明请求?** (对比不同版本的前台服务权限差异及适配方法) 3. **后台服务如何与Activity进行通信?** (使用`Messenger`、`LiveData`或`Broadcast`的通信方案) 4. **后台服务被系统终止后如何恢复任务状态?** (使用`WorkManager`持久化任务状态) 5. **如何避免后台服务被系统限制?** (针对不同Android版本的后台优化策略)</think>### 解决 Android Theme.NoDisplay 报错问题及正确实现无 Activity 启动应用 #### 问题分析 引用[1][4]指出,在 Android 6.0+ 设备上使用 `Theme.NoDisplay` 主题会导致 ANR 问题。这是因为系统会等待 Activity 显示窗口,但由于主题设置为不显示,系统在等待 5 秒后会触发 ANR。Google 官方建议使用 `Theme.Translucent.NoTitleBar` 替代实现透明无界面效果。 #### 正确实现无 Activity 启动应用的方案 ##### 1. 使用透明主题替代 NoDisplay ```xml <!-- AndroidManifest.xml --> <activity android:name=".LaunchActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:exported="true" android:excludeFromRecents="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ``` ##### 2. 启动 Activity 实现(立即启动服务并退出) ```java public class LaunchActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 启动后台服务 Intent serviceIntent = new Intent(this, BackgroundService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent); } else { startService(serviceIntent); } // 关键:立即结束Activity finish(); } } ``` ##### 3. 后台服务实现(同之前方案) ```java public class BackgroundService extends Service { @Override public void onCreate() { super.onCreate(); // 创建前台通知(Android 8.0+必需) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForeground(NOTIFICATION_ID, createNotification()); } } // 其他服务实现代码... } ``` #### 关键优化点说明 1. **主题替换原则** - 使用 `Theme.Translucent.NoTitleBar` 替代 `Theme.NoDisplay` - 透明主题不会触发窗口显示等待,避免 ANR - 保持完全无界面的用户体验 2. **Activity 生命周期控制** - 在 `onCreate()` 中启动服务后立即调用 `finish()` - **禁止调用** `setContentView()` 方法 - 设置 `android:excludeFromRecents="true"` 隐藏最近任务列表 3. **深度链接处理方案** 对于需要处理 deep link 的场景(引用[5]),使用以下配置: ```xml <activity android:name=".RouterActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:excludeFromRecents="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" /> </intent-filter> </activity> ``` #### 不同场景的适配方案 | **场景** | **实现方案** | |------------------------|----------------------------------------------------------------------------| | 应用冷启动 | 透明Activity启动服务后立即finish | | 深度链接(Deep Link) | 透明Activity处理路由后启动服务 | | 后台任务触发 | 直接通过Context启动服务(需处理Android 8.0+限制) | | 设备重启后自动启动 | 使用`BOOT_COMPLETED`广播接收器(需动态权限) | #### 常见问题解决 1. **ANR 问题** - 确认使用 `Theme.Translucent.NoTitleBar` 而非 `NoDisplay` - 检查是否在 `onCreate()` 中调用了 `finish()` - 确保没有调用 `setContentView()` 方法 2. **Activity 残留问题** ```java protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 不要设置布局! startService(); finish(); // 必须立即调用 } ``` 3. **Android 12+ 适配** - 添加权限:`<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>` - 声明前台服务类型: ```xml <service android:name=".BackgroundService" android:foregroundServiceType="location|microphone"/> ``` > **最佳实践**:对于需要长期运行的后台任务,建议结合 `WorkManager` 实现,以符合最新的后台限制政策[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值