Skip to content

Commit

Permalink
Merge pull request tidev#133 from billdawson/timob-1529
Browse files Browse the repository at this point in the history
Timob 1529 Get transparency into activity windows
  • Loading branch information
donthorp committed Jun 22, 2011
2 parents ddd8d89 + b54cf3d commit dc058a4
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 59 deletions.
89 changes: 66 additions & 23 deletions android/modules/ui/src/ti/modules/titanium/ui/TiUIWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
import org.appcelerator.titanium.TiContext;
import org.appcelerator.titanium.TiMessageQueue;
import org.appcelerator.titanium.TiModalActivity;
import org.appcelerator.titanium.TiTranslucentActivity;
import org.appcelerator.titanium.proxy.ActivityProxy;
import org.appcelerator.titanium.proxy.TiViewProxy;
import org.appcelerator.titanium.proxy.TiWindowProxy;
import org.appcelerator.titanium.util.Log;
import org.appcelerator.titanium.util.TiBindingHelper;
Expand Down Expand Up @@ -387,33 +387,63 @@ public void run() {
}
}

private void handleBackgroundColor(Object value, boolean post)
private void handleBackground(Drawable drawable, Object opacityValue, boolean post)
{
if (value != null) {
Drawable cd = TiConvert.toColorDrawable(TiConvert.toString(value));
if (drawable != null) {
if (opacityValue != null && !lightWeight) { // lightweight opacity will get handled via super because nativeView won't be null.
setActivityOpacity(drawable, TiConvert.toFloat(opacityValue), true);
}
if (lightWeight) {
nativeView.setBackgroundDrawable(cd);
nativeView.setBackgroundDrawable(drawable);
} else {
setActivityBackground(cd, post);
setActivityBackground(drawable, post);
}
}
}
private void handleBackgroundColor(Object value, boolean post)
{
KrollDict d = resolver.findProperty(TiC.PROPERTY_OPACITY);
if (d != null && d.containsKey(TiC.PROPERTY_OPACITY)) {
handleBackgroundColor(value, d.get(TiC.PROPERTY_OPACITY), post);
} else {
handleBackgroundColor(value, null, post);
}
}
private void setActivityOpacity(Drawable background, float opacity, boolean firstTime)
{
int alpha = Math.round(opacity * 255);
if (alpha > 254 && firstTime) {
alpha = 254; // why? seems if there is no transparency when window first displayed, Android won't allow it later either
} else if (alpha < 0) {
alpha = 0;
}
background.setAlpha(alpha);
}
private void handleBackgroundColor(Object value, Object opacityValue, boolean post)
{
if (value != null) {
Drawable cd = TiConvert.toColorDrawable(TiConvert.toString(value));
handleBackground(cd, opacityValue, post);
} else {
Log.w(LCAT, "Unable to set opacity w/o a backgroundColor");
}
}

private void handleBackgroundImage(Object value, boolean post)
{
KrollDict d = resolver.findProperty(TiC.PROPERTY_OPACITY);
if (d != null && d.containsKey(TiC.PROPERTY_OPACITY)) {
handleBackgroundImage(value, d.get(TiC.PROPERTY_OPACITY), post);
} else {
handleBackgroundImage(value, null, post);
}
}
private void handleBackgroundImage(Object value, Object opacityValue, boolean post)
{
if (value != null) {
String path = proxy.getTiContext().resolveUrl(null, TiConvert.toString(value));
TiFileHelper tfh = new TiFileHelper(proxy.getContext().getApplicationContext());
Drawable bd = tfh.loadDrawable(proxy.getTiContext(), path, false);
if (bd != null) {
if (lightWeight) {
nativeView.setBackgroundDrawable(bd);
} else {
setActivityBackground(bd, post);
}
}
handleBackground(bd, opacityValue, post);
}
}

Expand All @@ -422,9 +452,17 @@ public void processProperties(KrollDict d)
{
// Prefer image to color.
if (d.containsKey(TiC.PROPERTY_BACKGROUND_IMAGE)) {
handleBackgroundImage(d.get(TiC.PROPERTY_BACKGROUND_IMAGE), true);
if (d.containsKey(TiC.PROPERTY_OPACITY)) {
handleBackgroundImage(d.get(TiC.PROPERTY_BACKGROUND_IMAGE), d.get(TiC.PROPERTY_OPACITY), true);
} else {
handleBackgroundImage(d.get(TiC.PROPERTY_BACKGROUND_IMAGE), true);
}
} else if (d.containsKey(TiC.PROPERTY_BACKGROUND_COLOR)) {
handleBackgroundColor(d.get(TiC.PROPERTY_BACKGROUND_COLOR), true);
if (d.containsKey(TiC.PROPERTY_OPACITY)) {
handleBackgroundColor(d.get(TiC.PROPERTY_BACKGROUND_COLOR), d.get(TiC.PROPERTY_OPACITY), true);
} else {
handleBackgroundColor(d.get(TiC.PROPERTY_BACKGROUND_COLOR), true);
}
}
if (d.containsKey(TiC.PROPERTY_TITLE)) {
String title = TiConvert.toString(d, TiC.PROPERTY_TITLE);
Expand Down Expand Up @@ -503,6 +541,8 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
layout.setLayoutArrangement(TiConvert.toString(newValue));
}
}
} else if (key.equals(TiC.PROPERTY_OPACITY)) {
setOpacity(TiConvert.toFloat(newValue));
} else {
super.propertyChanged(key, oldValue, newValue, proxy);
}
Expand Down Expand Up @@ -535,13 +575,18 @@ protected Intent createIntent(Activity activity)
intent.putExtra(TiC.PROPERTY_NAV_BAR_HIDDEN, TiConvert.toBoolean(props, TiC.PROPERTY_NAV_BAR_HIDDEN));
}
props = resolver.findProperty(TiC.PROPERTY_MODAL);
boolean modal = false;
if (props != null && props.containsKey(TiC.PROPERTY_MODAL)) {
boolean modal = TiConvert.toBoolean(props, TiC.PROPERTY_MODAL);
modal = TiConvert.toBoolean(props, TiC.PROPERTY_MODAL);
intent.putExtra(TiC.PROPERTY_MODAL, modal);
if (modal) {
intent.setClass(activity, TiModalActivity.class);
}
}
props = resolver.findProperty(TiC.PROPERTY_OPACITY);
if (props != null && props.containsKey(TiC.PROPERTY_OPACITY) && !modal) { // modal already translucent
intent.setClass(activity, TiTranslucentActivity.class);
}
props = resolver.findProperty(TiC.PROPERTY_URL);
if (props != null && props.containsKey(TiC.PROPERTY_URL)) {
intent.putExtra(TiC.PROPERTY_URL, TiConvert.toString(props, TiC.PROPERTY_URL));
Expand Down Expand Up @@ -573,14 +618,12 @@ protected Intent createIntent(Activity activity)
@Override
public void setOpacity(float opacity)
{
View view = null;
if (!lightWeight) {
view = windowActivity.getWindow().getDecorView();
if (lightWeight) {
super.setOpacity(nativeView, opacity);
} else {
view = nativeView;
setActivityOpacity(windowActivity.getWindow().getDecorView().getBackground(), opacity, false);
windowActivity.getWindow().getDecorView().invalidate();
}

super.setOpacity(view, opacity);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2009-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
package org.appcelerator.titanium;


public class TiTranslucentActivity extends TiActivity
{
}
4 changes: 4 additions & 0 deletions apidoc/Titanium/UI/Window.yml
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ properties:
description: for modal windows, hide the nav bar (true) or show the nav bar (false, default).
default: false
type: Boolean
- name: opacity
description: |
The opacity from 0.0-1.0. Android Notes: If you set any of `windowSoftInputMode`, `fullscreen`, or `navBarHidden`, *and* you wish to use the `opacity` property at any time during the window's lifetime, be sure to set an `opacity` value before opening the window. You can later change that value -- and you can set it to 1 for full opacity if you wish -- but the important thing is that you set it to a value before opening the window if you will want to set it at any time during the window's lifetime. The technical reason for this is that if the opacity property is present (i.e., has been set to something) and a new Android Activity will be created for the window, then a translucent theme will be used for the Activity. Window transparency (opacity values below 1) will only work in Android if the Activity's theme is translucent, and we will only use a translucent theme for an Activity if you set an opacity property before opening the window. Additionally, do not use `opacity` and `fullscreen: true` together, because translucent themes in Android cannot hide the status bar. Finally, if you do set the `opacity` property, be sure to also set a `backgroundImage` or `backgroundColor` property as well, unless you want the window to be completely transparent.
type: Number
- name: orientationModes
description: array of orientation mode constants defined in [Titanium.UI]
type: Array<Object>
Expand Down
9 changes: 9 additions & 0 deletions demos/KitchenSink/Resources/main_windows/base_ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ tableview.addEventListener('click', function(e)
{
win.hideTabBar();
}
if (Ti.Platform.name==='android' && e.rowData.test.indexOf('window_properties.js') >= 0) {
// As explained in apidoc for Window, if opacity is ever to be changed for an Android
// activity during its lifetime, it needs to use a translucent background. We trigger
// using a translucent theme by the presence of the opacity property, so we need to
// set it here. Setting it to 1 means it's totally opaque, but gives us the property to
// make it more transparent later with the "toggle opacity" test.
win.backgroundColor = "#191919"
win.opacity = 1;
}
Titanium.UI.currentTab.open(win,{animated:true});
}
});
Expand Down
64 changes: 28 additions & 36 deletions support/android/templates/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,54 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="${config['appid']}"
android:versionCode="${config['appversion']}"
android:versionName="${config['appversion']}"
>
package="${config['appid']}" android:versionCode="${config['appversion']}"
android:versionName="${config['appversion']}">
<uses-sdk android:minSdkVersion="7" />

<!-- TI_MANIFEST -->

<application
android:icon="@drawable/appicon"
android:label="${config['appname']}"
android:name="${config['classname']}Application"
android:debuggable="false"
>

<application android:icon="@drawable/appicon"
android:label="${config['appname']}" android:name="${config['classname']}Application"
android:debuggable="false">

<!-- TI_APPLICATION -->
<activity
android:name=".${config['classname']}Activity"
android:label="${config['appname']}"
android:theme="@style/Theme.Titanium"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity android:name=".${config['classname']}Activity"
android:label="${config['appname']}" android:theme="@style/Theme.Titanium"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- TI_ACTIVITIES -->
<activity
android:name="org.appcelerator.titanium.TiActivity"
android:configChanges="keyboardHidden|orientation"
/>

<activity android:name="org.appcelerator.titanium.TiActivity"
android:configChanges="keyboardHidden|orientation" />
<activity android:name="org.appcelerator.titanium.TiTranslucentActivity"
android:configChanges="keyboardHidden|orientation"
android:theme="@android:style/Theme.Translucent" />
<activity android:name="org.appcelerator.titanium.TiModalActivity"
android:configChanges="keyboardHidden|orientation"
android:theme="@android:style/Theme.Translucent"
/>
android:theme="@android:style/Theme.Translucent" />
<activity android:name="ti.modules.titanium.ui.TiTabActivity"
android:configChanges="keyboardHidden|orientation"
/>
android:configChanges="keyboardHidden|orientation" />
<activity android:name="ti.modules.titanium.ui.android.TiPreferencesActivity" />

<service
android:name="org.appcelerator.titanium.analytics.TiAnalyticsService"
android:exported="false"
/>
<service android:name="org.appcelerator.titanium.analytics.TiAnalyticsService"
android:exported="false" />
<!-- TI_SERVICES -->

</application>

<!-- TI_PERMISSIONS -->

</manifest>

0 comments on commit dc058a4

Please sign in to comment.