Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-10015] Android: Gradient colors offset property, when unspecified, crashes app

GitHub Issuen/a
TypeBug
PriorityHigh
StatusClosed
ResolutionFixed
Resolution Date2012-09-06T03:36:34.000+0000
Affected Version/sRelease 2.1.0, Release 2.1.1
Fix Version/sSprint 2012-15 API, Release 3.0.0
ComponentsAndroid
Labelsapi, module_view, parity, qe-review, qe-testadded, titanbeta
ReporterShawn Lipscomb
AssigneeJosh Roesslein
Created2012-07-12T11:55:28.000+0000
Updated2013-11-07T05:52:59.000+0000

Description

Problem

If you leave off the *offset* property of elements in the *colors* array of a Gradient, the app crashes.

Expected behavior

First element of the *colors* array should default to offset:0.0, and the second element of the *colors* array should default to offset:1.0, as this is a common case (full width or height gradient). Alternatively, a console error or "red & white error screen" should be produced when the *offset* property is not specified.

Actual bahavior

A "force close" occurs with this crash error in the console log: {panel:title=console log}
[ERROR][TiApplication(  526)] (main) [104,104] Sending event: exception on thread: main msg:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.eCotton.GradientTest/org.appcelerator.titanium.TiActivity}: java.lang.NullPointerException; Titanium 2.1.0,2012/06/28 12:16,6e3cab6
[ERROR][TiApplication(  526)] java.lang.RuntimeException: Unable to start activity ComponentInfo{com.eCotton.GradientTest/org.appcelerator.titanium.TiActivity}: java.lang.NullPointerException
[ERROR][TiApplication(  526)] 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
[ERROR][TiApplication(  526)] 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
[ERROR][TiApplication(  526)] 	at android.app.ActivityThread.access$2300(ActivityThread.java:125)
[ERROR][TiApplication(  526)] 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
[ERROR][TiApplication(  526)] 	at android.os.Handler.dispatchMessage(Handler.java:99)
[ERROR][TiApplication(  526)] 	at android.os.Looper.loop(Looper.java:123)
[ERROR][TiApplication(  526)] 	at android.app.ActivityThread.main(ActivityThread.java:4627)
[ERROR][TiApplication(  526)] 	at java.lang.reflect.Method.invokeNative(Native Method)
[ERROR][TiApplication(  526)] 	at java.lang.reflect.Method.invoke(Method.java:521)
[ERROR][TiApplication(  526)] 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
[ERROR][TiApplication(  526)] 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
[ERROR][TiApplication(  526)] 	at dalvik.system.NativeStart.main(Native Method)
[ERROR][TiApplication(  526)] Caused by: java.lang.NullPointerException
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.util.TiConvert.toFloat(TiConvert.java:432)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.util.TiConvert.toFloat(TiConvert.java:462)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.view.TiGradientDrawable.loadColors(TiGradientDrawable.java:106)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.view.TiGradientDrawable.<init>(TiGradientDrawable.java:83)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.view.TiUIView.handleBackgroundImage(TiUIView.java:824)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.view.TiUIView.processProperties(TiUIView.java:594)
[ERROR][TiApplication(  526)] 	at ti.modules.titanium.ui.widget.TiView.processProperties(TiView.java:49)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.KrollProxy.setModelListener(KrollProxy.java:884)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.realizeViews(TiViewProxy.java:441)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.handleGetView(TiViewProxy.java:433)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.getOrCreateView(TiViewProxy.java:411)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.handleAdd(TiViewProxy.java:527)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:204)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.proxy.TiWindowProxy.handleMessage(TiWindowProxy.java:111)
[ERROR][TiApplication(  526)] 	at ti.modules.titanium.ui.ActivityWindowProxy.handleMessage(ActivityWindowProxy.java:93)
[ERROR][TiApplication(  526)] 	at android.os.Handler.dispatchMessage(Handler.java:95)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.common.TiMessenger.dispatchMessage(TiMessenger.java:365)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.common.TiMessenger.dispatchPendingMessages(TiMessenger.java:350)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.common.TiMessenger$2.getResult(TiMessenger.java:235)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.common.TiMessenger.sendBlockingMessage(TiMessenger.java:262)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.common.TiMessenger.sendBlockingRuntimeMessage(TiMessenger.java:187)
[ERROR][TiApplication(  526)] 	at org.appcelerator.kroll.KrollProxy.fireSyncEvent(KrollProxy.java:605)
[ERROR][TiApplication(  526)] 	at ti.modules.titanium.ui.TiUIActivityWindow.windowCreated(TiUIActivityWindow.java:142)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.TiActivityWindows.windowCreated(TiActivityWindows.java:31)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.TiBaseActivity.windowCreated(TiBaseActivity.java:352)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.TiBaseActivity.onCreate(TiBaseActivity.java:425)
[ERROR][TiApplication(  526)] 	at org.appcelerator.titanium.TiActivity.onCreate(TiActivity.java:22)
[ERROR][TiApplication(  526)] 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
[ERROR][TiApplication(  526)] 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
[ERROR][TiApplication(  526)] 	... 11 more
[ERROR][AndroidRuntime(  526)] FATAL EXCEPTION: main
[ERROR][AndroidRuntime(  526)] java.lang.RuntimeException: Unable to start activity ComponentInfo{com.eCotton.GradientTest/org.appcelerator.titanium.TiActivity}: java.lang.NullPointerException
[ERROR][AndroidRuntime(  526)] 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
[ERROR][AndroidRuntime(  526)] 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
[ERROR][AndroidRuntime(  526)] 	at android.app.ActivityThread.access$2300(ActivityThread.java:125)
[ERROR][AndroidRuntime(  526)] 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
[ERROR][AndroidRuntime(  526)] 	at android.os.Handler.dispatchMessage(Handler.java:99)
[ERROR][AndroidRuntime(  526)] 	at android.os.Looper.loop(Looper.java:123)
[ERROR][AndroidRuntime(  526)] 	at android.app.ActivityThread.main(ActivityThread.java:4627)
[ERROR][AndroidRuntime(  526)] 	at java.lang.reflect.Method.invokeNative(Native Method)
[ERROR][AndroidRuntime(  526)] 	at java.lang.reflect.Method.invoke(Method.java:521)
[ERROR][AndroidRuntime(  526)] 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
[ERROR][AndroidRuntime(  526)] 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
[ERROR][AndroidRuntime(  526)] 	at dalvik.system.NativeStart.main(Native Method)
[ERROR][AndroidRuntime(  526)] Caused by: java.lang.NullPointerException
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.util.TiConvert.toFloat(TiConvert.java:432)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.util.TiConvert.toFloat(TiConvert.java:462)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.view.TiGradientDrawable.loadColors(TiGradientDrawable.java:106)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.view.TiGradientDrawable.<init>(TiGradientDrawable.java:83)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.view.TiUIView.handleBackgroundImage(TiUIView.java:824)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.view.TiUIView.processProperties(TiUIView.java:594)
[ERROR][AndroidRuntime(  526)] 	at ti.modules.titanium.ui.widget.TiView.processProperties(TiView.java:49)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.KrollProxy.setModelListener(KrollProxy.java:884)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.realizeViews(TiViewProxy.java:441)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.handleGetView(TiViewProxy.java:433)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.getOrCreateView(TiViewProxy.java:411)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.handleAdd(TiViewProxy.java:527)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.proxy.TiViewProxy.handleMessage(TiViewProxy.java:204)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.proxy.TiWindowProxy.handleMessage(TiWindowProxy.java:111)
[ERROR][AndroidRuntime(  526)] 	at ti.modules.titanium.ui.ActivityWindowProxy.handleMessage(ActivityWindowProxy.java:93)
[ERROR][AndroidRuntime(  526)] 	at android.os.Handler.dispatchMessage(Handler.java:95)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.common.TiMessenger.dispatchMessage(TiMessenger.java:365)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.common.TiMessenger.dispatchPendingMessages(TiMessenger.java:350)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.common.TiMessenger$2.getResult(TiMessenger.java:235)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.common.TiMessenger.sendBlockingMessage(TiMessenger.java:262)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.common.TiMessenger.sendBlockingRuntimeMessage(TiMessenger.java:187)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.kroll.KrollProxy.fireSyncEvent(KrollProxy.java:605)
[ERROR][AndroidRuntime(  526)] 	at ti.modules.titanium.ui.TiUIActivityWindow.windowCreated(TiUIActivityWindow.java:142)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.TiActivityWindows.windowCreated(TiActivityWindows.java:31)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.TiBaseActivity.windowCreated(TiBaseActivity.java:352)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.TiBaseActivity.onCreate(TiBaseActivity.java:425)
[ERROR][AndroidRuntime(  526)] 	at org.appcelerator.titanium.TiActivity.onCreate(TiActivity.java:22)
[ERROR][AndroidRuntime(  526)] 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
[ERROR][AndroidRuntime(  526)] 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
[ERROR][AndroidRuntime(  526)] 	... 11 more
[WARN][ActivityManager(   60)]   Force finishing activity com.eCotton.GradientTest/org.appcelerator.titanium.TiActivity
{panel}

Testcase

Run the following code. A white-to-red vertical gradient box should appear at the top of the screen, but instead the app crashes. Now uncomment the offset code. The box appears with the correct gradient. {panel:title=app.js}
var win1=Ti.UI.createWindow({
                 layout:'vertical',
                 backgroundColor:'gray',
                 exitOnClose:true,
                 navBarHidden:true
               });

var view1=Ti.UI.createView({
                  height:100,
                  width:100,
                  backgroundGradient:{type:'linear',
                                      endPoint:{ x:0, y:'100%' },
                                      colors:[ {color:'white' /*, offset:0.0*/ },
                                               {color:'red' /*, offset:1.0*/ } ]}
                });
win1.add(view1);

win1.open();
{panel}

Comments

  1. Josh Roesslein 2012-07-19

    The recommend way to create gradients that evenly distribute the colors is to just provide them in an array:
       Ti.UI.createView({
         backgroundGradient: {
           colors: ['white', 'red']
         }
       });
       
    We could provide the same functionality with the gradient color objects, but this becomes a bit more difficult when you start mixing objects that have offsets and some that don't provide an offset.
  2. Josh Roesslein 2012-07-19

    Created [PR #2615](https://github.com/appcelerator/titanium_mobile/pull/2615) to resolve issue.
  3. Josh Roesslein 2012-07-19

    Ended up fixing the exception and matching iOS behavior by just discarding the offsets when the number of offsets does not match the number of colors.
  4. Shawn Lipscomb 2012-07-20

    Josh, thanks for fixing this. I also didn't know that we could use the *colors**:* *['white', 'red']* syntax (I'm pretty sure that isn't in the online API docs), but I will start using it that way since it's cleaner.
  5. Tamila Smolich 2012-08-13

    Closing as fixed. Tested and verified on: Titanium Studio, build: 2.1.1.201208091713 Titanium SDK, build: 2.2.0.v20120810194112 Devices: Nexus 7 tab (4.1), HTC Evo (4.0.3), Android Emulator (2.2) The box appears with white-to-red vertical gradient.
  6. Anshu Mittal 2012-09-06

    Reopening to update labels
  7. Shameer Jan 2013-11-07

    Anvil testcase PR https://github.com/appcelerator/titanium_mobile/pull/4887

JSON Source