{ "id": "119556", "key": "TIMOB-15092", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": null, "resolutiondate": null, "created": "2013-09-05T22:23:30.000+0000", "priority": { "name": "Low", "id": "4" }, "labels": [ "android", "classname", "picker", "pickers", "tableView", "tableviewrow" ], "versions": [ { "id": "15479", "description": "Release 3.1.2", "name": "Release 3.1.2", "archived": true, "released": true, "releaseDate": "2013-07-31" } ], "issuelinks": [], "assignee": null, "updated": "2018-02-28T20:03:15.000+0000", "status": { "description": "The issue is open and ready for the assignee to start work on it.", "name": "Open", "id": "1", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "components": [ { "id": "10202", "name": "Android", "description": "Android Platform" } ], "description": "h4. Problem Description\r\nWhen you add multiple Pickers inside a TableView (one picker per row), they get very buggy after scrolling the screen.\r\n\r\nWhat I have noticed is that some previously selected pickerView options just disappear, or the options are changed randomly.\r\n\r\nIn the testcase I'm submitting I'm using the same options for different pickerviews, but if the options are different the problem get even worse.\r\n\r\nI have also found out that If I set a className to each different pickerView ROW the problem vanishes. Problem is that it seems that there is a limit of 32 classNames, past that and the app crashes (which is a big problem as I'm building dynamic forms and some forms reach 50+ questions).\r\nAlso, by setting a different className to each row, you lose the tableView optimization.\r\n\r\nh4. Testcase\r\n{code}\r\n\r\nvar w = Ti.UI.createWindow({\r\n backgroundColor: \"#dddcdc\",\r\n navBarHidden: true,\r\n fullscreen: false,\r\n orientationModes: [Ti.UI.PORTRAIT],\r\n windowSoftInputMode: Ti.UI.Android.SOFT_INPUT_ADJUST_PAN,\r\n});\r\n\r\n\r\n/*\r\n * QUESTIONS\r\n */\r\n\r\n\r\nvar rows = [],\r\n fields = [],\r\n multiOpts = {};\r\n\r\nfor (var i = 0; i <= 50; i++) {\r\n\r\n var r = Ti.UI.createTableViewRow({\r\n backgroundColor: \"#dedede\",\r\n height: 153,\r\n width: Ti.UI.FILL,\r\n className: \"rowQuestion\"\r\n });\r\n\r\n var qNum = Ti.UI.createLabel({\r\n text: i + 1,\r\n top: 15,\r\n left: -5,\r\n width: \"10%\",\r\n height: 31,\r\n color: \"#fff\",\r\n textAlign: \"center\",\r\n backgroundColor: \"#82b52a\",\r\n borderRadius: 15,\r\n touchEnabled: false,\r\n font: {\r\n fontSize: 14,\r\n fontFamily: \"Roboto-Regular\"\r\n }\r\n });\r\n\r\n var qTitle = Ti.UI.createLabel({\r\n text: \"This is a question title asking something for the user...\",\r\n top: 0,\r\n left: \"10%\",\r\n width: \"90%\",\r\n height: 70,\r\n color: \"#333\",\r\n verticalAlign: Ti.UI.TEXT_VERTICAL_ALIGNMENT_TOP,\r\n font: {\r\n fontSize: 14,\r\n fontFamily: \"Roboto-Regular\"\r\n }\r\n });\r\n\r\n // Field\r\n fields[i] = Ti.UI.createPicker({\r\n width: \"80%\",\r\n height: 60,\r\n top: 85,\r\n font: {\r\n fontSize: 14,\r\n fontWeight: \"bold\"\r\n },\r\n color: \"#888\"\r\n });\r\n\r\n \r\n fields[i].add([\r\n \tTi.UI.createPickerRow({title: \"\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 1\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 2\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 3\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 4\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 5\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 6\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 7\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 8\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 9\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 10\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 11\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 12\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 13\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 14\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 15\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 16\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 17\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 18\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 19\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 20\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 21\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 22\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 23\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 24\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 25\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 26\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 27\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 28\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 29\"}),\r\n \tTi.UI.createPickerRow({title: \"Option Test Option 30\"}),\r\n ]);\r\n\r\n r.add(qNum);\r\n r.add(qTitle);\r\n r.add(fields[i]);\r\n\r\n rows.push(r);\r\n\r\n}\r\n\r\n\r\n\r\nvar t = Ti.UI.createTableView({\r\n\tseparatorColor: \"#a6a6a6\",\r\n\tdata: rows\r\n});\r\n\r\nw.add(t);\r\n\r\nw.open();\r\n\r\n{code}\r\n\r\nh4. Instructions to reproduce\r\n1. Create a new mobile Project (Classic Titanium)\r\n2. Paste the code into app.js\r\n3. Run it in a device\r\n4. In question 0, put answer 0, in question 1, answer 1 and so on. \r\n5. Scroll down and up.\r\n6. You will see your answers changed. \r\n\r\nh4. Extra info\r\nIn the logs I can see this:\r\n{code}\r\n09-09 13:28:05.914: W/InputMethodManagerService(523): Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@429b75c8 attribute=null, token = android.os.BinderProxy@42a76558\r\n{code}\r\n\r\nwhen scrolling the tableview.\r\n\r\n", "attachment": [], "flagged": false, "summary": "Android: Multiple PickerViews inside a TableView shuffling options / disappearing", "creator": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "subtasks": [], "reporter": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "environment": "Ti SDK 3.1.2.GA (Tested also on 3.1.1.GA)\r\nTested on Multiple Android Devices (Samsung Galaxy S4, Samsung Galaxy S3, Nexus 7, LG L5, Motorola Razr, Nexus 4)\r\nTested on Multiple Android Versions (4.0, 4.1, 4.2, 4.3)", "comment": { "comments": [ { "id": "269990", "author": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Ygor, could you update with a few items?\n\n# Can you add a screenshot?\n# Do you have an example use case? We're not arguing that it's invalid, we're just curious how you are using this.\n# There was a suggestion to use a ScrollView or something besides a TableView. Have you tried that?", "updateAuthor": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-09-06T18:22:11.000+0000", "updated": "2013-09-06T18:22:11.000+0000" }, { "id": "269998", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "Hi Ingo,\n\n1 - Sure, I'll make a quick video so you guys can see the problem happening as its nature is dynamic and can't really be expressed on a screenshot.\n2 - Yes. I already have an app published on the App Store with over 20k users here in Brazil. Basically this is part of my dynamic form generator, where missions which are basically mobile forms with several kinds of fields are rendered on the device from a JSON specification that comes from the network. The app is similar to Gigwalk / Field Agent / iPoll and others, the name of the app is PiniOn.\n3 - Yes, I saw that and I've tried it, but the rows structure of a table view seriously optimize the way we assembly those dynamic forms as the field types and amount of fields change severely from one mission to another... Imagine all kinds of forms being rendered natively on mobile devices. (The same codebase works both on iOS and Android).\n\nI'll send a video showing the current behaviour ASAP.\nAlso, I've sent the rows with lots of formatting, feel free to remove them from the testcase, the error reproduces even with bare rows.", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-09-06T18:33:18.000+0000", "updated": "2013-09-06T18:33:18.000+0000" }, { "id": "270001", "author": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Is there a way you could change to use a ListView? ListView, in general, is the preferred approach over TableView.", "updateAuthor": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-09-06T18:43:09.000+0000", "updated": "2013-09-06T18:43:09.000+0000" }, { "id": "270012", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "Moving to a ListView is on our Roadmap but it is way in the future since it requires a lot of rewriting.\n\nSince the tableViews are quite good for our current needs right now, we haven't prioritized moving the form rendered to a ListView, we have tested the dynamic forms with 100+ fields of all kinds (text, boolean, numeric, pickers, multi-select, photo capture with thumbnails, QR code scanning, etc...), all mixed inside the same form and the performance is quite good, even on slow entry-level android devices. On iOS the performance is even greater.\n\nI'd rather keep the tableViews for a couple more months since we are near our public Android release (we are Beta testing on the Play Store for a week now).", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-09-06T19:06:27.000+0000", "updated": "2013-09-06T19:06:27.000+0000" }, { "id": "270013", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "This is the video showing the current TC behavior on a Nexus 7. The same repeats on every device we tested.\n\nhttp://www.youtube.com/watch?v=8ap8uaPOoxE\n", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-09-06T19:08:10.000+0000", "updated": "2013-09-06T19:08:10.000+0000" }, { "id": "270300", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "If you apply a different className to each row containing a Picker, the problem vanishes.\nThe problem (apart the obvious lost of any kind of optimization by cell reusing) is that it seems there is some kind of limit on how many classNames you can use... when you reach around 32 classnames, you get an error like this:\n\n\n{code}\njava.lang.ArrayIndexOutOfBoundsException: length=32; index=32\nat android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:7009)\nat android.widget.AbsListView.trackMotionScroll(AbsListView.java:5532)\nat android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3404)\nat android.widget.AbsListView.onTouchEvent(AbsListView.java:3748)\nat android.view.View.dispatchTouchEvent(View.java:7146)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2238)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1935)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)\nat android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2244)\nat android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1949)\nat com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1938)\nat com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1392)\nat android.app.Activity.dispatchTouchEvent(Activity.java:2408)\nat com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1886)\nat android.view.View.dispatchPointerEvent(View.java:7332)\nat android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3520)\nat android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3454)\nat android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4543)\nat android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4522)\nat android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4618)\nat android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)\nat android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)\nat android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:163)\nat android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:4597)\nat android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:4637)\nat android.view.Choreographer$CallbackRecord.run(Choreographer.java:747)\nat android.view.Choreographer.doCallbacks(Choreographer.java:567)\nat android.view.Choreographer.doFrame(Choreographer.java:534)\nat android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:733)\nat android.os.Handler.handleCallback(Handler.java:615)\nat android.os.Handler.dispatchMessage(Handler.java:92)\nat android.os.Looper.loop(Looper.java:153)\nat android.app.ActivityThread.main(ActivityThread.java:4987)\nat java.lang.reflect.Method.invokeNative(Native Method)\nat java.lang.reflect.Method.invoke(Method.java:511)\nat com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)\nat com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)\nat dalvik.system.NativeStart.main(Native Method)\n{code}\n\n\n", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-09-09T14:18:59.000+0000", "updated": "2013-09-09T14:18:59.000+0000" }, { "id": "270447", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "Can anybody give me a light on how to get a PickerView inside a ListItem on a ListView?\r\n\r\nI'm trying to migrate this TC to a ListView to see if this problem also happens within ListViews, but I'm stuck on how to add the PickerRows to the Pickers since I have no reference to their instance thus preventing me to access .add() on the PickerViews.\r\n\r\n\r\nI have created the templates (for the same rows of the TC), please point me out on how to add the Rows and I will finish this TC using ListViews:\r\n\r\n\r\n{code}\r\n\r\nvar w = Ti.UI.createWindow({\r\n backgroundColor: \"#dddcdc\",\r\n navBarHidden: true,\r\n fullscreen: false,\r\n orientationModes: [Ti.UI.PORTRAIT],\r\n windowSoftInputMode: Ti.UI.Android.SOFT_INPUT_ADJUST_PAN,\r\n});\r\n\r\n\r\n\r\nvar myTemplate = {\r\n childTemplates: [\r\n { \r\n type: 'Ti.UI.Label',\r\n bindId: 'qNum',\r\n properties: {\r\n top: 15,\r\n\t\t left: -5,\r\n\t\t width: \"10%\",\r\n\t\t height: 31,\r\n\t\t color: \"#fff\",\r\n\t\t textAlign: \"center\",\r\n\t\t backgroundColor: \"#82b52a\",\r\n\t\t borderRadius: 15,\r\n\t\t touchEnabled: false,\r\n\t\t font: {\r\n\t\t fontSize: 14,\r\n\t\t fontFamily: \"Roboto-Regular\"\r\n\t\t }\r\n }\r\n },\r\n { \r\n type: 'Ti.UI.Label',\r\n bindId: 'qTitle',\r\n properties: {\r\n top: 0,\r\n\t\t left: \"10%\",\r\n\t\t width: \"90%\",\r\n\t\t height: 70,\r\n\t\t color: \"#333\",\r\n\t\t verticalAlign: Ti.UI.TEXT_VERTICAL_ALIGNMENT_TOP,\r\n\t\t font: {\r\n\t\t fontSize: 14,\r\n\t\t fontFamily: \"Roboto-Regular\"\r\n \t\t}\r\n }\r\n },\r\n {\r\n type: 'Ti.UI.Picker',\r\n bindId: 'qPicker',\r\n properties: {\r\n width: \"80%\",\r\n\t\t height: 60,\r\n\t\t top: 85,\r\n\t\t font: {\r\n\t\t fontSize: 14,\r\n\t\t fontWeight: \"bold\"\r\n\t\t },\r\n\t\t color: \"#888\"\r\n }\r\n }\r\n ]\r\n};\r\n\r\n\r\nvar sections = [];\r\n\r\nvar questions = Ti.UI.createListSection({ headerTitle: 'Questions'});\r\nvar questionsData = [];\r\n\r\n\r\n/*\r\n * QUESTIONS\r\n */\r\n\r\n\r\nvar rows = [],\r\n fields = [],\r\n multiOpts = {};\r\n\r\nfor (var i = 0; i <= 50; i++) {\r\n\r\n questionsData.push({\r\n\t\tqNum: {text: i+1},\r\n\t\tqTitle: {text: \"This is a whatever question \" + i}\r\n });\r\n \r\n /*\r\n * \r\n * HOW DO I ADD THE PickerRows (options) TO THE PICKER qPicker here ????\r\n * \r\n * \r\n */\r\n\r\n}\r\n\r\nvar listView = Ti.UI.createListView({\r\n templates: { 'template': myTemplate },\r\n defaultItemTemplate: 'template'\r\n});\r\n\r\nquestions.setItems(questionsData);\r\nsections.push(questions);\r\n\r\nlistView.setSections(sections);\r\n\r\n\r\nw.add(listView);\r\n\r\nw.open();\r\n\r\n\r\n{code}\r\n\r\n\r\nThanks.", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-09-09T22:02:24.000+0000", "updated": "2013-09-09T22:02:24.000+0000" }, { "id": "272710", "author": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "body": "Any news on this one?\r\n\r\nThis still prevents devs from using Pickers inside tableViews as of 3.1.3.GA...", "updateAuthor": { "name": "ygbr", "key": "ygbr", "displayName": "Ygor Lemos", "active": true, "timeZone": "America/Sao_Paulo" }, "created": "2013-09-24T20:04:44.000+0000", "updated": "2013-09-24T20:04:44.000+0000" } ], "maxResults": 9, "total": 9, "startAt": 0 } } }