Skip to content

Commit

Permalink
feat(android): use material theme by default
Browse files Browse the repository at this point in the history
- Changed default theme from "Theme.AppCompat" to "Theme.MaterialComponents.Bridge".
  * The material bridge uses the same dark theme as AppCompat and adds the new material styles.
- Fixed bug where modal/translucent windows ignore "tiapp.xml" setting <navbar-hidden/>.
- Added new Titanium themes which derive from custom theme assigned to app.
- Deprecated "Theme.AppCompat.*" since material widgets require a material theme.

Fixes TIMOB-27714, TIMOB-28084, TIMOB-28087
  • Loading branch information
jquick-axway authored and sgtcoolguy committed Sep 28, 2020
1 parent 6d84fc0 commit 00e2816
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 61 deletions.
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,5 @@ dependencies {
}

implementation "androidx.appcompat:appcompat:${project.ext.tiAndroidXAppCompatLibVersion}"
implementation "com.google.android.material:material:${project.ext.tiMaterialLibVersion}"
}
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<application android:name=".TitaniumTestApplication" android:icon="@drawable/appicon" android:label="TitaniumTest" android:theme="@style/Theme.AppCompat" android:usesCleartextTraffic="true">
<application android:name=".TitaniumTestApplication" android:icon="@drawable/appicon" android:label="TitaniumTest" android:theme="@style/Theme.MaterialComponents.Bridge" android:usesCleartextTraffic="true">
<activity android:name=".TitaniumTestActivity" android:theme="@style/Theme.Titanium" android:alwaysRetainTaskState="true" android:configChanges="${tiActivityConfigChanges}">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
Expand Down
43 changes: 19 additions & 24 deletions android/cli/commands/_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -1658,6 +1658,14 @@ AndroidBuilder.prototype.initialize = async function initialize() {
const loadFromSDCardProp = this.tiapp.properties['ti.android.loadfromsdcard'];
this.loadFromSDCard = loadFromSDCardProp && loadFromSDCardProp.value === true;

// Set default theme to be used in "AndroidManifest.xml" and style resources.
this.defaultAppThemeName = 'Theme.MaterialComponents.Bridge';
if (this.tiapp.fullscreen || this.tiapp['statusbar-hidden']) {
this.defaultAppThemeName = 'Theme.MaterialComponents.Fullscreen.Bridge';
} else if (this.tiapp['navbar-hidden']) {
this.defaultAppThemeName = 'Theme.MaterialComponents.NoActionBar.Bridge';
}

// Array of gradle/maven compatible library reference names the app project depends on.
// Formatted as: "<group.id>:<artifact-id>:<version>"
// Example: "com.google.android.gms:play-services-base:11.0.4"
Expand Down Expand Up @@ -3409,20 +3417,16 @@ AndroidBuilder.prototype.generateTheme = async function generateTheme() {
const xmlFilePath = path.join(valuesDirPath, 'ti_styles.xml');
this.logger.info(__('Generating theme file: %s', xmlFilePath.cyan));

// Set up all "Base.Theme.Titanium.Basic" inherited themed activities to be fullscreen if enabled in "tiapp.xml".
let basicParentThemeName = 'Theme.AppCompat';
if (this.tiapp.fullscreen || this.tiapp['statusbar-hidden']) {
basicParentThemeName += '.Fullscreen';
}

// Set up all "Base.Theme.Titanium.Customizable" inherited themes to use one of the following:
// - The custom theme applied to the <application/> element in "AndroidManifest.xml".
// - The above fullsceen enabled basic theme if custom theme was not applied.
let customizableParentThemeName = basicParentThemeName;
// Set up "Base.Theme.Titanium.Customizable" inherited themes to use <application/> defined theme, if provided.
// Note: Do not assign it if set to a Titanium theme, which would cause a circular reference.
let customizableParentThemeName = this.defaultAppThemeName;
if (this.customAndroidManifest) {
let appTheme = this.customAndroidManifest.getAppAttribute('android:theme');
if (appTheme && appTheme.startsWith('@style/') && (appTheme !== '@style/Theme.Titanium.Translucent')) {
customizableParentThemeName = appTheme.replace('@style/', '');
const appTheme = this.customAndroidManifest.getAppAttribute('android:theme');
if (appTheme) {
const appThemeWithoutPrefix = appTheme.replace('@style/', '');
if (!appThemeWithoutPrefix.startsWith('Theme.Titanium') && !appThemeWithoutPrefix.startsWith('Base.Theme.Titanium')) {
customizableParentThemeName = appTheme;
}
}
}

Expand All @@ -3431,7 +3435,7 @@ AndroidBuilder.prototype.generateTheme = async function generateTheme() {
let xmlLines = [
'<?xml version="1.0" encoding="utf-8"?>',
'<resources>',
` <style name="Base.Theme.Titanium.Basic" parent="${basicParentThemeName}"/>`,
` <style name="Base.Theme.Titanium.Basic" parent="${this.defaultAppThemeName}"/>`,
` <style name="Base.Theme.Titanium.Customizable" parent="${customizableParentThemeName}"/>`,
'',
' <!-- Theme used by "TiRootActivity" derived class which displays the splash screen. -->',
Expand Down Expand Up @@ -3558,15 +3562,6 @@ AndroidBuilder.prototype.generateAndroidManifest = async function generateAndroi
this.logger.warn(__n(message));
}

// Choose app theme to be used by all activities depending on following "tiapp.xml" settings.
let appThemeName = '@style/Theme.AppCompat';
if (this.tiapp.fullscreen || this.tiapp['statusbar-hidden'] || this.tiapp['navbar-hidden']) {
appThemeName += '.NoTitleBar';
if (this.tiapp.fullscreen || this.tiapp['statusbar-hidden']) {
appThemeName += '.Fullscreen';
}
}

// Generate all XML lines to be added as children within the manifest's <application/> block.
const appChildXmlLines = [];
if (this.tiapp.android) {
Expand Down Expand Up @@ -3637,7 +3632,7 @@ AndroidBuilder.prototype.generateAndroidManifest = async function generateAndroi
appChildXmlLines: appChildXmlLines,
appIcon: '@drawable/' + this.tiapp.icon.replace(/((\.9)?\.(png|jpg))$/, ''),
appLabel: this.tiapp.name,
appTheme: appThemeName,
appTheme: `@style/${this.defaultAppThemeName}`,
classname: this.classname,
packageName: this.appid
});
Expand Down
4 changes: 2 additions & 2 deletions android/cli/tests/test-android-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ describe('AndroidManifest', () => {
it('set/getAppAttribute()', () => {
const manifest = new AndroidManifest();
manifest.setAppAttribute('android:icon', '@drawable/app_icon');
manifest.setAppAttribute('android:theme', '@style/Theme.AppCompat');
manifest.setAppAttribute('android:theme', '@style/Theme.MaterialComponents.Bridge');
expect(manifest.getAppAttribute('android:icon')).to.equal('@drawable/app_icon');
expect(manifest.getAppAttribute('android:theme')).to.equal('@style/Theme.AppCompat');
expect(manifest.getAppAttribute('android:theme')).to.equal('@style/Theme.MaterialComponents.Bridge');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light"/>

<org.appcelerator.titanium.view.TiCompositeLayout
android:layout_width="match_parent"
Expand Down
2 changes: 1 addition & 1 deletion android/modules/ui/res/layout/titanium_ui_toolbar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light"
android:fitsSystemWindows="true"/>
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TitaniumAngular" parent="Theme.AppCompat.Light.DarkActionBar">
<style name="TitaniumAngular" parent="Theme.MaterialComponents.Light.DarkActionBar.Bridge">
<item name="colorPrimary">@color/angularBlue</item>
<item name="colorPrimaryDark">@color/angularDarkBlue</item>
<item name="colorAccent">@color/angularRed</item>
<item name="android:windowBackground">@color/windowBackground</item>
<item name="android:textColor">#444</item>
</style>
</style>
</resources>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar.Bridge">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
Expand Down
4 changes: 2 additions & 2 deletions android/titanium/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
<activity
android:name="ti.modules.titanium.media.TiCameraActivity"
android:configChanges="${tiActivityConfigChanges}"
android:theme="@style/Theme.AppCompat.Translucent.NoTitleBar.Fullscreen"/>
android:theme="@style/Theme.Titanium.Translucent.Fullscreen"/>
<activity
android:name="ti.modules.titanium.media.TiVideoActivity"
android:configChanges="${tiActivityConfigChanges}"
android:theme="@style/Theme.AppCompat.Fullscreen"/>
android:theme="@style/Theme.Titanium.Fullscreen"/>
<activity android:name="ti.modules.titanium.ui.android.TiPreferencesActivity"/>

<provider
Expand Down
101 changes: 74 additions & 27 deletions android/titanium/res/values/values.xml
Original file line number Diff line number Diff line change
@@ -1,67 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base theme applied to all Titanium transluent windows and splash activity. -->
<!-- Our "_build.js" script will replace it with ".Fullscreen" theme if set in "tiapp.xml" file. -->
<style name="Base.Theme.Titanium.Basic" parent="Theme.AppCompat"/>
<!-- Base theme applied to Titanium's splash screen activity. -->
<!-- Our "_build.js" will replace it with ".NoActionBar" or ".Fullscreen" theme if set in "tiapp.xml" file. -->
<style name="Base.Theme.Titanium.Basic" parent="Theme.MaterialComponents.Bridge"/>

<!-- Base theme applied to all Titanium opaque windows. -->
<!-- Our "_build.js" script will replace it if custom theme is applied to application in manifest. -->
<style name="Base.Theme.Titanium.Customizable" parent="Theme.AppCompat"/>

<!-- Base theme to be used by the "TiRootActivity" class. -->
<style name="Base.Theme.Titanium.Splash" parent="@style/Base.Theme.Titanium.Basic">
<style name="Base.Theme.Titanium.Splash" parent="Base.Theme.Titanium.Basic">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<style name="Theme.AppCompat.NoTitleBar">
<item name="android:windowNoTitle">true</item>
<!-- Theme to be replaced by app project and have a "windowBackground" image applied to it. -->
<!-- Our Android "_build.js" script will replace this theme via the generateTheme() method. -->
<style name="Theme.Titanium" parent="Base.Theme.Titanium.Splash"/>

<!-- Activity theme used to remove top title bar, but keeps status bar and app theme. -->
<style name="Theme.Titanium.NoTitleBar" parent="Base.Theme.Titanium.Customizable">
<item name="android:windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<!-- Activity theme used to remove top status bar and title bar while preserving app theme. -->
<style name="Theme.Titanium.Fullscreen" parent="Theme.Titanium.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>

<!-- Activity theme applying transparent background while preserving app theme. -->
<style name="Theme.Titanium.Translucent" parent="Base.Theme.Titanium.Customizable">
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
</style>

<!-- Activity theme applying transparent background and removes title bar, while preserving app theme. -->
<style name="Theme.Titanium.Translucent.NoTitleBar" parent="Theme.Titanium.Translucent">
<item name="android:windowActionBar">false</item>
<!-- AppCompat Compatibility -->
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<style name="Theme.AppCompat.NoTitleBar.Fullscreen">
<!-- Activity theme with transparent background, removes status bar and title bar while preserving app theme. -->
<style name="Theme.Titanium.Translucent.Fullscreen" parent="Theme.Titanium.Translucent.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>

<style name="Theme.AppCompat.Fullscreen" parent="@style/Theme.AppCompat.NoTitleBar.Fullscreen"/>
<!-- Inherits Google's "Theme.MaterialComponents.Bridge" and removes top status and title bar. -->
<style name="Theme.MaterialComponents.Fullscreen.Bridge" parent="Theme.MaterialComponents.Bridge">
<item name="android:windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<!-- Theme to be replaced by app project and have a "windowBackground" image applied to it. -->
<!-- Our Android "_build.js" script will replace this theme via the generateTheme() method. -->
<style name="Theme.Titanium" parent="@style/Base.Theme.Titanium.Splash"/>
<!-- Google's dark AppCompat activity theme without a top title bar. -->
<!-- DEPRECATED: Should use MaterialComponents theme instead in order to use material widgets. -->
<style name="Theme.AppCompat.NoTitleBar" parent="Theme.AppCompat">
<item name="android:windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<!-- Theme to be used by Titanium's translucent windows and modal windows. -->
<style name="Theme.Titanium.Translucent" parent="@style/Base.Theme.Titanium.Customizable">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<!-- Google's dark AppCompat activity theme without a top status bar and title bar. -->
<!-- DEPRECATED: Should use MaterialComponents theme instead in order to use material widgets. -->
<style name="Theme.AppCompat.NoTitleBar.Fullscreen" parent="Theme.AppCompat.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>

<style name="Theme.AppCompat.Translucent" parent="@style/Base.Theme.Titanium.Basic">
<!-- Google's dark AppCompat activity theme without a top status bar and title bar. -->
<!-- DEPRECATED: Should use MaterialComponents theme instead in order to use material widgets. -->
<style name="Theme.AppCompat.Fullscreen" parent="Theme.AppCompat.NoTitleBar.Fullscreen"/>

<!-- Google's dark AppCompat activity theme with a transparent background. -->
<!-- DEPRECATED: Should use MaterialComponents theme instead in order to use material widgets. -->
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:actionBarStyle">@style/Base.Widget.AppCompat.ActionBar.Solid</item>
<!-- AppCompat Compatibility -->
<item name="actionBarStyle">@style/Base.Widget.AppCompat.ActionBar.Solid</item>
</style>
<style name="Theme.AppCompat.Translucent.NoTitleBar">
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>

<!-- Google's dark AppCompat activity theme with a transparent background without a title bar. -->
<!-- DEPRECATED: Should use MaterialComponents theme instead in order to use material widgets. -->
<style name="Theme.AppCompat.Translucent.NoTitleBar" parent="Theme.AppCompat.Translucent">
<item name="android:windowActionBar">false</item>
<!-- AppCompat Compatibility -->
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<style name="Theme.AppCompat.Translucent.NoTitleBar.Fullscreen">

<!-- Google's dark AppCompat activity theme with a transparent background without a status bar and title bar. -->
<!-- DEPRECATED: Should use MaterialComponents theme instead in order to use material widgets. -->
<style name="Theme.AppCompat.Translucent.NoTitleBar.Fullscreen" parent="Theme.AppCompat.Translucent.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>
</resources>

0 comments on commit 00e2816

Please sign in to comment.