Android 产品定制之资源定制(同一应用程序使用不同资源)

前言

前两天面试一家公司(当然我没去),他们那边的工作要求是把一个软件发布多个不同的版本,每个稍微修改一些UI。就类似于同一软件发布多个不同名的版本,本质代码还是一样的,不过可能有些文字或者图片的变化。面试官跟我说你来的话任务很简单,就是不停地复制粘贴和改名。虽然我没去那家公司入职,但我也想了想那边任务的实现方式。复制粘贴?No!我们有更好的方法!下面我们来介绍如何创建多个不同版本的相同的应用程序。

基础版本

首先我们做一个基础版本的app,很简单,从第一个页面点击按钮到第二个页面,从第二个页面点击按钮到第三个页面。整体如图:
这里写图片描述
项目目录如下:
这里写图片描述
只是三个很简单的Activity。

进行定制

接下来,我们进行项目的定制。制作一个在第二个页面(SecondActivity)展示不同文字的定制版本。
首先,使用Android闭包的productFlavors块来声明一个产品定制。代码如下:

android {
    compileSdkVersion 27
    defaultConfig {
        flavorDimensions(versionName)
    }

    productFlavors{
        customone{
            applicationId "learn.song.com.customone"
        }
        customtwo{
            applicationId "learn.song.com.customtwo"
        }
        customthree{
            applicationId "learn.song.com.customthree"
        }
    }
}

注意,新的Gradle版本要求在defaultConfig里声明flavorDimensions
本项目中,我们有customone,customtwo,customthree三种定制版本,每个定制拥有一个略微不同的applicationId,所以这三个定制版本可以被安装到同一个设备上。
每个产品定制可以拥有其自己的值,如下面的属性,还有一些其他的基于默认的defaultConfig的相同属性。
- applicationId
- minSdkVersion
- targetSdkVersion
- versionCode
- versionName
- sigingConfig
接下来,我们开始着手定制customone。打开工程视图,在app/src下建立customone文件夹,与main文件夹同级。项目结构如下:
这里写图片描述
下一步,我们定制customone,在SecondActivity里显示不同的文字,下面我们看SecondActivity的xml文件代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SecondActivity">
    <TextView
        android:layout_marginTop="40dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/tv_second_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/secondpage"
        />
    <TextView
        android:id="@+id/tv_second_next"
        android:padding="10dp"
        android:background="#cf1414"
        android:layout_marginTop="40dp"
        android:layout_gravity="center_horizontal"
        android:text="Go To Thrid Page"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

可见,我们第一个Textview显示的文字来自资源文件strings.xmlandroid:text="@string/secondpage",我们看我们基础版本的strings.xml:

<resources>
    <string name="app_name">My Application</string>
    <string name="title_activity_thrid">ThridActivity</string>
    <string name="title_home">Home</string>
    <string name="title_dashboard">Dashboard</string>
    <string name="title_notifications">Notifications</string>
    <string name="secondpage">Hello SecondPage From Main!</string>
</resources>

secondpage对应的文字是Hello SecondPage From Main!。好,接下来我们在customone对其定制,让我们customone版本显示的文字为Hello SecondPage From CustomOne!。怎么做呢?跟随我一步一步来。
1. 在customone文件夹下建立res文件夹,其就相当于main文件夹下的res,现在它是我们定制的res文件。我们要定制secondpage的值,那么我们要新建res/values/strings.xml,新的项目结构如下:
这里写图片描述
重写strings.xml,修改secondpage的值。我所定制的customone下strings.xml具体代码如下:

<resources>
    <string name="app_name">My CustomOne</string>
    <string name="title_activity_thrid">ThridActivity</string>
    <string name="title_home">Home</string>
    <string name="title_dashboard">Dashboard</string>
    <string name="title_notifications">Notifications</string>
    <string name="secondpage">Hello SecondPage From CustomOne!</string>
</resources>

主要就是修改了secondpage的值。接下来我们运行一下。要运行不同的定制,Android Studio提供了一个Build Variant视图。从下拉框中选择合适的变种,并像平常一样部署。 如图:
这里写图片描述
我们可以看到三个不同定制的Debug版本和Release版本。我们运行customoneDebug,效果如下:
这里写图片描述
看第二个页面(SecondActivity),上面的文字已经改变,但是我们并没有重新copy一套代码,而是直接在原代码上进行了定制。

通过合并项目定制和构建类型的res文件夹以及主要的目录树来合并资源。优先级是:构建类型覆盖产品定制,其覆盖main代码集。

为了更好的理解,接下来我们继续定制SecondActivity,在红色按钮下面显示一张妹子的图片。如何定制呢?跟之前思路一样,在customone/res下建立layout文件夹,重写activity_second.xml,重写之后的activity_second.xml如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".SecondActivity">
    <TextView
        android:layout_marginTop="40dp"
        android:layout_gravity="center_horizontal"
        android:id="@+id/tv_second_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/secondpage"
        />
    <TextView
        android:id="@+id/tv_second_next"
        android:padding="10dp"
        android:background="#cf1414"
        android:layout_marginTop="40dp"
        android:layout_gravity="center_horizontal"
        android:text="Go To Thrid Page"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <ImageView
        android:layout_gravity="center_horizontal"
        android:src="@mipmap/img_meizi"
        android:layout_marginTop="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

项目结构如下:
这里写图片描述
再看看我们customone定制版本的运行效果:
这里写图片描述
此时,第二个页面多出了我们刚刚添加的妹子的图片。与此同时,我们没有动过手脚的customtwo和customthree版本仍旧与基础版本一样,仍然保留着我们最初的效果。

结尾

刚刚我们对原始的项目进行了定制,产生了新的变种,展示了不同的页面效果。但是如果我们需要该某些activity的java代码应该怎么做呢?copy吗?当然不是,如果需要定制java代码,请看我的下一篇文章Android 产品定制之java代码定制(同一应用程序某个Activity使用不同java代码)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值