Android:主题切换

这篇具有很好参考价值的文章主要介绍了Android:主题切换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.概述

正在开发的应用做了一版新UI,原打算将新版UI按项目名做成资源包,再在build.gradle里productFlavors{ }多渠道打包实现

但被告知新旧两个项目共用一个分支,那就做成两个主题(Theme1/Theme2)来适配了

如果只是变更UI,做成多主题来适配不同项目也是比较合适的方式

一.Android App实现多主题的主要有如下几种:

  1. 从服务器下载或提前放置不同主题资源包到设备指定目录,在代码里引用主题资源
  2. 定义不同的<style>、使用Android的setTheme()机制设置不同主题
  3. 将主题资源做成APK,使用远程Context的方式访问Apk中的主题资源。

第1、第3种方法的实现原理,是用户从服务器下载 或 提前放置主题资源,然后在代码中进行引用

第2种方法是接下来先要讲的, 也是这次新旧UI开发适配完成的方式。

第2种讲完后,也会同步介绍第1、第3种方法

除了这三种常用的方式外,还有一种通过"修改framework中Resources类获取资源的流程,将资源重定向到主题包中"的实现方式,这种方式暂不做讨论

二.setTheme()实现主题切换

2.1 定义属性(attr)

App的UI由各种布局文件实现,布局文件中要定义Android各类UI属性(drawable、colors、mipmap、dimension、string......)引用UI资源。

先将Theme1、Theme2各布局文件中都有定义但需要引用不同值的UI属性挑出来,按照不同类型在/values/attrs.xml中进行定义:

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <attr name="ColorAttrName" format="color" />  
    <attr name="integerAttrName" format="integer" />  
    <attr name="booleanAttrName" format="boolean" />  
    <attr name="dimensionAttrName" format="dimension" />  
    <item name="floatAttrName" format="dimension" />  
    <attr name="stringAttrName" format="string" />  
    <attr name="referenceAttrName" format="reference" />  
</resources>  

reference主要对应drawable、mipmap资源,其他的看字面意思

2.2 定义主题(Theme1/Theme2)

/values/style.xml中定义Theme1、Theme2

<style name="ThemeBlack" parent="@android:style/Theme.Black">  
    <item name="colorAttrName">#FF00FF00</item>  
    <item name="integerAttrName">33</item>  
    <item name="booleanAttrName">true</item>  
    <item name="dimensionAttrName">76dp</item>
    <item name="floatAttrName">0.35</item>    
    <item name="stringAttrName">@string/hello_world</item>  
    <item name="referenceAttrName">@drawable/hand</item>  
</style>

<style name="ThemeLight" parent="@android:style/Theme.Light">  
    <item name="colorAttrName">#FFFFFF00</item>  
    <item name="integerValue">55</item>  
    <item name="booleanAttrName">false</item>  
    <item name="dimensionValue">76px</item>  
    <item name="floatAttrName">0.15</item>    
    <item name="stringAttrName">@string/action_settings</item>  
    <item name="referenceAttrName">@drawable/ic_launcher</item>  
</style>

各属性的具体值可以在Theme定义时配置,但是最好定义在各自的xml配置文件中(color.xml、string.xml、dimens.xml.....),然后在Theme定义时"@类型/..."格式引用

Theme中如果string类型不是引用而是字符串,在布局文件中使用正常,但代码里获取会有问题

2.3 布局文件中引用属性

使用过程也很简单,原本布局文件中引用UI属性的方式如下:

android:color="@color/colorAttrName"
android:duration="@integer/integerValue"
android:adjustViewBounds="@bool/booleanAttrName" 
android:layout_height="@dimen/dimensionValue"
android:text="@string/stringAttrName"
android:background="@drawable/referenceAttrName"

现在改为这样进行引用:

android:color="?attr/colorAttrName"
android:duration="?attr/integerValue"
android:adjustViewBounds="?attr/booleanAttrName" 
android:layout_height="?attr/dimensionValue"
android:text="?attr/stringAttrName"
android:background="?attr/referenceAttrName"

float比较特殊,一般它会在代码中被引用(后面会讲到),配置文件中多在dimens.xml中定义变量

2.4 代码中切换主题

要配置的都配置好了,需要注意的是:

  • 最好写一个BaseActivity,其他的Activitiy都继承至它
  • 主题设置需要在setContentView()之前

接下来就在代码中进行主题切换:

package com.android.example.ui;

import android.os.Bundle;

import com.android.example.R;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (setThemeBlack) {
            setTheme(R.style.ThemeBlack);
        } else {
            setTheme(R.style.ThemeLight);
        }
    }
}

主题设置写在BaseActivity的onCreate()函数中,它会在其他所有继承至它的Activity的onCreate()之前运行。

2.5 代码中引用属性

如果要在代码中引用 integerValue、floatAttrName、booleanAttrName,使用Context.obtainStyledAttributes()就可以了

package com.android.example.ui;

import android.os.Bundle;

import com.android.example.R;

import android.content.res.TypedArray;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class BaseActivity extends AppCompatActivity {


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (setThemeBlack) {
            setTheme(R.style.ThemeBlack);
        } else {
            setTheme(R.style.ThemeLight);
        }

        TypedArray tyar = obtainStyledAttributes(new int[]{
                R.attr.colorValue,
                R.attr.integerValue,
                R.attr.booleanValue,
                R.attr.dimensionValue,
                R.attr.floatValue,
                R.attr.stringValue,
                R.attr.referenceValue
        });

        int colorArrtValue = tyar.getColor(0, Color.BLACK);
        int integerArrtValue = tyar.getInt(1, Integer.MAX_VALUE);
        boolean booleanArrtValue = tyar.getBoolean(2, false);
        float dimensionArrtValue = tyar.getDimensionPixelSize(3, 66);
        float floatArrtValue = tyar.getFloat(4, 99.99f);
        String stringArrtValue = tyar.getString(5);
        Drawable drawableArrtValue = tyar.getDrawable(6);
    }
}

到此,通过setTheme()切换主题方式就讲述完毕了 

这种切换主题方式的优点是:不需要修改太多代码,大部分修改只要针对布局文件就行。

弊端就是:主题只能内置配置好,一旦程序发布后,应用支持的主题类型就固定了,要想增加更多主题,只能发布新的版本。

如果想要动态配置主题,可以使用前文中提到过第1、第3种主题切换方式。

就是接下来要讲的内容了

三.主题资源打包成Apk进行切换

Apk主题切换和第1种将主题包整体下载或提前放置的方案很像。

共同点是:都需要在代码中动态设置图片、文字、颜色等UI信息。

区别是:第1种方法需要自行编写资源解析的方法。而Apk主题切换,可以使用Android自带Api

APK主题方案的基本思路是:

在Android中,所有的资源都是基于包的。资源以id进行标识,在同一个应用中,每个资源都有唯一标识。但在不同的应用中,可以有相同的id。

因此,只要获取到了其他应用的Context对象,就可以通过它的 getRsources() 获取到其绑定的资源对象。

然后,就可以使用 Resources 的 getXXX 方法获取字符串、颜色、dimension、图片等。

要想获取其他应用的Context对象,Android已经为我们提供好了接口:

android.content.ContextWrapper.createPackageContext(String packageName, int flags)

package com.android.example.ui;

import android.os.Bundle;
import androidx.annotation.Nullable;

public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView text = (TextView) findViewById(R.id.remoteText);
        TextView color = (TextView) findViewById(R.id.remoteColor);
        ImageView image = (ImageView) findViewById(R.id.remote_image);

        try {
            //主题资源Apk包名
            String remotePackage = "com.xxx.themepackage";
            //主题资源Apk Context
            Context remoteContext = createPackageContext(remotePackage,CONTEXT_IGNORE_SECURITY);
            //主题资源Apk Resources
            Resources remoteResources = remoteContext.getResources();

            text.setText(remoteResources.getText(remoteResources.getIdentifier("application_name", "string", remotePackage)));
            color.setTextColor(remoteResources.getColor(remoteResources.getIdentifier("delete_target_hover_tint", "color", remotePackage)));
            image.setImageDrawable(remoteResources.getDrawable(remoteResources.getIdentifier("ic_launcher_home", "drawable", remotePackage)));
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
    }
}

四.综述

3.高级应用

内置主题实现简单、配置方便,但可扩展性不强。

Apk切换主题扩展性高,但要在代码里设置所有可变资源,一旦界面布局改变,需要较长时间进行代码改写。

实际运用中,可以将以上两种结合起来使用:

涉及到界面风格,如整体色调、不同的文字颜色,使用内置主题。图片资源则在APK主题包中提供。文章来源地址https://www.toymoban.com/news/detail-676146.html

到了这里,关于Android:主题切换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android style(样式) 和 theme(主题) 属性

            样式和主题资源都可用于对Android UI组件进行“美化”,只要充分利用好这两个属性资源,我们可以开发出各种风格的应用界面。         style 样式: 一个样式相当于多个格式的集合,其他UI组件通过style属性来指定样式,样式资源文件时放在/res/values/styles.xm

    2023年04月12日
    浏览(33)
  • 怎么设置Android Studio的(背景)主题颜色

    点击File,选择Settings… 点击Appearance,在Theme选择需要的主题颜色

    2024年02月12日
    浏览(32)
  • 【Android-JetpackCompose】11、主题设置:Theme、Colors、Typography、Shapes

    首先,从下面的仓库克隆代码: Material Design 定义了一些从语义上命名的颜色: primary 是主要品牌颜色,secondary 用于提供强调色。您可以为形成对比的区域提供颜色更深/更浅的变体。background 和 surface 这两种颜色用于那些容纳在概念上驻留在应用“Surface”的组件的容器。此外

    2024年02月05日
    浏览(33)
  • Android 横竖屏切换

    1.横竖屏切换 Android横竖屏要注意的问题: ①布局问题 ②重新载入问题 ③生命周期问题   2.布局问题 ①如果不想让app在横竖屏之间切换,可以在AndroidManifest.xml中指定的activity中加上android:screenOrientation属性,有以下几个参数: \\\"unspecified\\\":默认值 由系统来判断显示方向。判定

    2023年04月08日
    浏览(25)
  • android槽位切换

    可选命令 此时已经进入了fastboot,屏幕是黑的 查看当前槽位 A-B:swdl_utils -d 0 -l 1 B-A:swdl_utils -d 1 -l 1

    2024年02月06日
    浏览(20)
  • android 应用内切换语言

    1.1 选中res,右键选择Android Resource Directory = Locale = 选择你需要的语言 1.2 将values下的strings.xml复制到对应语言下的values下 1.3 将不同strings.xml中的内容改成对应的语言文字,不同strings.xml中同一个内容的name是相同的 1.4 在布局文件或者代码中引用strings.xml里的内容 我选择了英文和

    2023年04月08日
    浏览(23)
  • 【Android笔记107】Android之图像切换器ImageSwitcher的使用

    这篇文章,主要介绍Android之图像切换器ImageSwitcher的使用。 目录 一、ImageSwitcher 1.1、什么是ImageSwitcher (1)加载图片 (2)设置动画

    2024年02月07日
    浏览(31)
  • android实现点击按钮切换页面

    一、实现的功能 点击页面按钮,切换到下一个页面。 二、主要代码 1)第一个页面 我们需要实现点击登录按钮进行页面切换 layout中设置一个Button,仅展示按钮部分代码  登录页面LoginActivity代码, 三、启动页面 启动页面要设置为第一个页面,在AndroidMainfest.xml

    2024年02月08日
    浏览(47)
  • Android 动态切换应用图标方案

    经常听到大家讨论类似的需求,怀疑大厂是不是用了此方案,据我个人了解,多数头部 app 其实都是发版来更新节假日的 icon。当然本方案也是一种可选的方案,以前我也调研过,存在问题和作者所述差不多,此外原文链接作者也回复了很多疑问,可以同时了解。 市面上很多

    2024年02月01日
    浏览(37)
  • Android Navigation 导航切换fragment用法

    对于Android Navigation组件的导航到Fragment,您可以按照以下步骤操作: 首先,在您的项目的build.gradle文件中添加Navigation依赖: 在你的res目录下的navigation文件夹中创建一个nav_graph.xml文件,并定义您的导航图。 在您的布局文件中,添加NavHostFragment作为导航的目标。 在您的Activi

    2024年02月12日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包