Skip to content

Commit

Permalink
feat(android): add "solid" titanium app theme (#13030)
Browse files Browse the repository at this point in the history
Fixes TIMOB-28526
  • Loading branch information
jquick-axway committed Aug 25, 2021
1 parent 75ce8e4 commit ab3329e
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 19 deletions.
8 changes: 3 additions & 5 deletions android/app/src/main/assets/Resources/app.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use strict';

// create tab group
const tabGroup = Titanium.UI.createTabGroup();
const tabGroup = Titanium.UI.createTabGroup({
style: Ti.UI.Android.TABS_STYLE_BOTTOM_NAVIGATION,
});

//
// create base UI tab and root window
//
const win1 = Titanium.UI.createWindow({
title: 'Tab 1',
backgroundColor: '#fff'
});
const tab1 = Titanium.UI.createTab({
icon: 'KS_nav_views.png',
Expand All @@ -17,7 +18,6 @@ const tab1 = Titanium.UI.createTab({
});

const label1 = Titanium.UI.createLabel({
color: '#999',
text: 'I am Window 1',
font: { fontSize: 20, fontFamily: 'Helvetica Neue' },
textAlign: 'center',
Expand All @@ -31,15 +31,13 @@ win1.add(label1);
//
const win2 = Titanium.UI.createWindow({
title: 'Tab 2',
backgroundColor: '#fff'
});
const tab2 = Titanium.UI.createTab({
icon: 'KS_nav_ui.png',
title: 'Tab 2',
window: win2
});
var label2 = Titanium.UI.createLabel({
color: '#999',
text: 'I am Window 2',
font: { fontSize: 20, fontFamily: 'Helvetica Neue' },
textAlign: 'center',
Expand Down
6 changes: 3 additions & 3 deletions android/cli/commands/_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -3295,11 +3295,11 @@ AndroidBuilder.prototype.generateTheme = async function generateTheme() {
this.logger.info(__('Generating theme file: %s', xmlFileName.cyan));

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

// Set up "Theme.AppDerived" to use the <application/> defined theme, if assigned.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@
import org.appcelerator.kroll.common.Log;
import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.titanium.R;
import org.appcelerator.titanium.TiBaseActivity;
import org.appcelerator.titanium.TiC;
import org.appcelerator.titanium.proxy.ActivityProxy;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.proxy.TiWindowProxy;
import org.appcelerator.titanium.util.TiColorHelper;
import org.appcelerator.titanium.util.TiConvert;
import org.appcelerator.titanium.util.TiRHelper;
import org.appcelerator.titanium.util.TiUIHelper;
import org.appcelerator.titanium.view.TiInsetsProvider;
import org.appcelerator.titanium.view.TiUIView;

Expand Down Expand Up @@ -157,6 +158,8 @@ public abstract class TiUIAbstractTabGroup extends TiUIView
// endregion

// region private fields
private final boolean isUsingSolidTitaniumTheme;
private int colorBackgroundInt;
private int colorSurfaceInt;
private int colorPrimaryInt;
private int colorOnSurfaceInt;
Expand All @@ -169,22 +172,29 @@ public TiUIAbstractTabGroup(final TabGroupProxy proxy, TiBaseActivity activity)
{
super(proxy);

// Determines if theme has the "titaniumIsSolidTheme" attribute and it's set to "true".
// Used by our "Theme.Titanium.*.Solid" themes to shade the top/bottom tabs appropriately.
this.isUsingSolidTitaniumTheme = TiUIHelper.isUsingSolidTitaniumTheme(activity);

// Fetch primary background and text colors from ActionBar style assigned to activity theme.
// Note: We use ActionBar style for backward compatibility with Titanium versions older than 8.0.0.
this.colorBackgroundInt = Color.TRANSPARENT;
this.colorPrimaryInt = 0xFF212121; // Default to dark gray.
this.colorOnSurfaceInt = 0xFFBBBBBB; // Default to light gray.
this.colorSurfaceInt = Color.TRANSPARENT;
try {
final int[] idArray = new int[] {
TiRHelper.getResource("attr.colorPrimary"),
TiRHelper.getResource("attr.colorSurface"),
TiRHelper.getResource("attr.colorOnSurface")
android.R.attr.colorBackground,
R.attr.colorPrimary,
R.attr.colorSurface,
R.attr.colorOnSurface
};
final TypedArray typedArray = activity.getTheme().obtainStyledAttributes(idArray);

this.colorPrimaryInt = typedArray.getColor(0, this.colorPrimaryInt);
this.colorSurfaceInt = typedArray.getColor(1, this.colorSurfaceInt);
this.colorOnSurfaceInt = typedArray.getColor(2, this.colorOnSurfaceInt);
this.colorBackgroundInt = typedArray.getColor(0, this.colorBackgroundInt);
this.colorPrimaryInt = typedArray.getColor(1, this.colorPrimaryInt);
this.colorSurfaceInt = typedArray.getColor(2, this.colorSurfaceInt);
this.colorOnSurfaceInt = typedArray.getColor(3, this.colorOnSurfaceInt);
typedArray.recycle();
} catch (Exception ex) {
Log.e(TAG, "Failed to fetch color from theme.", ex);
Expand Down Expand Up @@ -464,7 +474,7 @@ public void processProperties(KrollDict d)
if (d.containsKeyAndNotNull(TiC.PROPERTY_TABS_BACKGROUND_COLOR)) {
setBackgroundColor(TiColorHelper.parseColor(d.get(TiC.PROPERTY_TABS_BACKGROUND_COLOR).toString()));
} else {
setBackgroundColor(this.colorSurfaceInt);
setBackgroundColor(getDefaultBackgroundColor());
}
super.processProperties(d);
}
Expand Down Expand Up @@ -549,12 +559,29 @@ public Drawable updateIconTint(TiViewProxy tabProxy, Drawable drawable, boolean
return drawable;
}

public boolean isUsingSolidTitaniumTheme()
{
return this.isUsingSolidTitaniumTheme;
}

@ColorInt
protected int getColorBackground()
{
return this.colorBackgroundInt;
}

@ColorInt
protected int getColorPrimary()
{
return this.colorPrimaryInt;
}

@ColorInt
protected int getDefaultBackgroundColor()
{
return this.colorSurfaceInt;
}

@ColorInt
protected int getActiveColor(TiViewProxy tabProxy)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
package ti.modules.titanium.ui.widget.tabgroup;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewParent;
import android.view.Window;

import androidx.annotation.ColorInt;
import androidx.core.graphics.ColorUtils;
Expand Down Expand Up @@ -298,12 +301,32 @@ public void selectTabItemInController(int position)
@Override
public void setBackgroundColor(int colorInt)
{
// Update tab bar's background color.
Drawable drawable = mBottomNavigationView.getBackground();
if (drawable instanceof MaterialShapeDrawable) {
((MaterialShapeDrawable) drawable).setFillColor(ColorStateList.valueOf(colorInt));
MaterialShapeDrawable shapeDrawable = (MaterialShapeDrawable) drawable;
shapeDrawable.setFillColor(ColorStateList.valueOf(colorInt));
shapeDrawable.setElevation(0); // Drawable will tint the fill color if elevation is non-zero.
} else {
mBottomNavigationView.setBackgroundColor(colorInt);
}

// Apply given color to bottom navigation bar if using a "solid" theme.
if (isUsingSolidTitaniumTheme() && (Build.VERSION.SDK_INT >= 27)) {
Activity activity = (this.proxy != null) ? this.proxy.getActivity() : null;
Window window = (activity != null) ? activity.getWindow() : null;
View decorView = (window != null) ? window.getDecorView() : null;
if ((window != null) && (decorView != null)) {
int uiFlags = decorView.getSystemUiVisibility();
if (ColorUtils.calculateLuminance(colorInt) > 0.5) {
uiFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
} else {
uiFlags &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
}
decorView.setSystemUiVisibility(uiFlags);
window.setNavigationBarColor(colorInt);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt;

import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.tabs.TabLayout;
Expand Down Expand Up @@ -203,6 +204,16 @@ public void setBackgroundColor(int colorInt)
this.mTabLayout.setBackgroundColor(colorInt);
}

@Override
@ColorInt
protected int getDefaultBackgroundColor()
{
if (isUsingSolidTitaniumTheme()) {
return getColorBackground();
}
return super.getDefaultBackgroundColor();
}

@Override
public void updateTabBackgroundDrawable(int index)
{
Expand Down
3 changes: 2 additions & 1 deletion android/titanium/res/values-night/values.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Titanium style supporting dark/light theme switching. -->
<!-- Titanium styles supporting dark/light theme switching. -->
<style name="Theme.Titanium.DayNight" parent="Theme.Titanium.Dark"/>
<style name="Theme.Titanium.DayNight.Solid" parent="Theme.Titanium.Dark.Solid"/>
</resources>
11 changes: 11 additions & 0 deletions android/titanium/res/values-v23/values.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Titanium.Light.Solid" parent="Theme.Titanium.Light">
<item name="android:navigationBarColor">@android:color/black</item>
<item name="android:statusBarColor">?android:attr/colorBackground</item>
<item name="android:windowLightStatusBar">true</item>
<item name="actionBarStyle">@style/Widget.AppCompat.Light.ActionBar</item>
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.ActionBar</item>
<item name="titaniumIsSolidTheme">true</item>
</style>
</resources>
12 changes: 12 additions & 0 deletions android/titanium/res/values-v27/values.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Titanium.Light.Solid" parent="Theme.Titanium.Light">
<item name="android:navigationBarColor">?android:attr/colorBackground</item>
<item name="android:statusBarColor">?android:attr/colorBackground</item>
<item name="android:windowLightNavigationBar">true</item>
<item name="android:windowLightStatusBar">true</item>
<item name="actionBarStyle">@style/Widget.AppCompat.Light.ActionBar</item>
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.ActionBar</item>
<item name="titaniumIsSolidTheme">true</item>
</style>
</resources>
79 changes: 78 additions & 1 deletion android/titanium/res/values/values.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
<!-- See "values-land/values.xml" which fixes action bar height for landscape. -->
<dimen name="ti_action_bar_height">@dimen/mtrl_toolbar_default_height</dimen>

<!-- Defines attribute indicating if a "Theme.Titanium.*.Solid" theme is being used at runtime. -->
<!-- Used by TabGroup to apply special handling to top/bottom tab bars. -->
<declare-styleable name="TitaniumTheme">
<attr name="titaniumIsSolidTheme" format="boolean"/>
</declare-styleable>

<!-- Define theme attribute used to customize Titanium's splash screen background drawable. -->
<declare-styleable name="TitaniumSplashBackground">
<attr name="titaniumSplashIcon" format="reference"/>
Expand Down Expand Up @@ -61,6 +67,32 @@
<item name="android:windowFullscreen">true</item>
</style>

<!-- Titanium's dark material theme with an action bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.Dark.Solid" parent="Theme.Titanium.Dark">
<item name="android:navigationBarColor">?android:attr/colorBackground</item>
<item name="android:statusBarColor">?android:attr/colorBackground</item>
<item name="actionBarStyle">@style/Widget.AppCompat.ActionBar</item>
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.Dark.ActionBar</item>
<item name="titaniumIsSolidTheme">true</item>
</style>

<!-- Titanium's dark material theme without an action bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.Dark.Solid.NoTitleBar" parent="Theme.Titanium.Dark.Solid">
<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>

<!-- Titanium's dark material theme without an action bar and status bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.Dark.Solid.Fullscreen" parent="Theme.Titanium.Dark.Solid.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>

<!-- Titanium's light material theme with an action bar. -->
<style name="Theme.Titanium.Light" parent="Theme.MaterialComponents.Light.DarkActionBar">
<item name="actionBarSize">@dimen/ti_action_bar_height</item>
Expand Down Expand Up @@ -91,6 +123,31 @@
<item name="android:windowFullscreen">true</item>
</style>

<!-- Titanium's light material theme with an action bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.Light.Solid" parent="Theme.Titanium.Light">
<item name="android:navigationBarColor">@android:color/black</item>
<item name="actionBarStyle">@style/Widget.AppCompat.Light.ActionBar</item>
<item name="actionBarTheme">@style/ThemeOverlay.MaterialComponents.ActionBar</item>
<item name="titaniumIsSolidTheme">true</item>
</style>

<!-- Titanium's light material theme without an action bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.Light.Solid.NoTitleBar" parent="Theme.Titanium.Light.Solid">
<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>

<!-- Titanium's light material theme without an action bar and status bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.Light.Solid.Fullscreen" parent="Theme.Titanium.Light.Solid.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>

<!-- Titanium style supporting dark/light theme switching with an action bar. -->
<style name="Theme.Titanium.DayNight" parent="Theme.Titanium.Light"/>

Expand All @@ -108,9 +165,29 @@
<item name="android:windowFullscreen">true</item>
</style>

<!-- Titanium style supporting dark/light theme switching with an action bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.DayNight.Solid" parent="Theme.Titanium.Light.Solid"/>

<!-- Titanium style supporting dark/light theme switching without an action bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.DayNight.Solid.NoTitleBar" parent="Theme.Titanium.DayNight.Solid">
<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>

<!-- Titanium style supporting dark/light theme switching without an action bar and status bar. -->
<!-- Status bar, action bar, and nav bar use same background color as window giving it one solid appearance. -->
<style name="Theme.Titanium.DayNight.Solid.Fullscreen" parent="Theme.Titanium.DayNight.Solid.NoTitleBar">
<item name="android:windowFullscreen">true</item>
</style>

<!-- The default theme Titanium applies to the <application/> in the manifest. -->
<!-- Our "_build.js" will replace parent with ".NoTitleBar" or ".Fullscreen" if set in "tiapp.xml". -->
<style name="Theme.Titanium.App" parent="Theme.Titanium.DayNight"/>
<style name="Theme.Titanium.App" parent="Theme.Titanium.DayNight.Solid"/>

<!-- The app theme which all Titanium activities will use by default. -->
<!-- Our "_build.js" will replace parent if "AndroidManifest.xml" was assigned a custom application theme. -->
Expand Down
Loading

0 comments on commit ab3329e

Please sign in to comment.