[TIMOB-28459] Android: ScrollableView with databinding in Footer/HeaderView not showing up
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | n/a |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2021-06-28T22:16:09.000+0000 |
Affected Version/s | n/a |
Fix Version/s | Release 10.0.1 |
Components | Android |
Labels | n/a |
Reporter | Michael Gangolf |
Assignee | Gary Mathews |
Created | 2021-05-20T11:43:28.000+0000 |
Updated | 2021-07-07T01:57:50.000+0000 |
Description
When you add a ScrollableView inside a HeaderView with databinding the child views aren't visible. I've rebuild the generated classic code from my Alloy app to make it easier to test but here is the original Alloy part first:
For my initial test I've used mocx (https://github.com/jasonkneen/mocx/blob/master/mocx.js) inside the lib folder and this code inside alloy.js:
var mocx = require("/mocx");
mocx.createCollection("contacts", [{name : "John Smith"}, {name : "Jane Doe"}]);
my xml:
<Alloy>
<Window fullscreen="true">
<ListView>
<ListSection dataCollection="contacts" bottom="200">
<HeaderView>
<View backgroundColor="#DDD" height="200">
<ScrollableView height="200" dataCollection="contacts" >
<!-- doesn't work -->
<View backgroundColor="red" height="200"/>
</ScrollableView>
</View>
</HeaderView>
<ListItem color="#000" title="{name}" searchableText="{name}"/>
<FooterView>
<View backgroundColor="#DDD" height="Ti.UI.SIZE">
<ScrollableView height="200" dataCollection="contacts">
<!-- doesn't work -->
<View backgroundColor="red" height="200"/>
</ScrollableView>
</View>
</FooterView>
</ListSection>
</ListView>
<ScrollableView height="200" dataCollection="contacts" bottom="0">
<ImageView image="/appicon.png"/>
</ScrollableView>
</Window>
</Alloy>
my controller
Alloy.Collections.contacts.fetch();
$.index.open();
the generated classic code looks like this:
for (var __alloyId7, opts = __alloyId11.opts || {}, models = __alloyId10.models, len = models.length, views = [], i = 0; i < len; i++) {
__alloyId7 = models[i], __alloyId7.__transform = transform(__alloyId7);
var __alloyId9 = Ti.UI.createView({
views: __alloyId6,
apiName: "Ti.UI.ScrollableView",
height: 200,
classes: [],
backgroundColor: "red"
});
views.push(__alloyId9);
}
$.__views.__alloyId5.views = views
It is adding the views to an array and set it to scrollableview.views
. So I've created a classic example that works in the same way (without databinding) which makes it easier to test:
const win = Ti.UI.createWindow({
backgroundColor: '#fff',
});
const sections = [];
var hv = Ti.UI.createView({
height: 100,
backgroundColor: "blue"
});
var sv = Ti.UI.createScrollableView({
height: 100,
backgroundColor: "yellow"
})
var views = [];
for (var i = 0; i < 10; ++i) {
var insideView = Ti.UI.createView({
height: 100,
backgroundColor: "rgba(" + (i * 20) + "," + i + "," + i + ")"
});
var lbl = Ti.UI.createLabel({
text:"should be visible",
color: "#fff"
})
insideView.add(lbl);
sv.addView(insideView)
}
hv.add(sv);
for (let i = 0; i < 3; i++) {
const items = [];
for (let x = 0; x < 5; x++) {
items.push({
label: {
text: Item #${x}
}
});
}
sections.push(Ti.UI.createListSection({
headerView: hv,
items
}));
}
const listView = Ti.UI.createListView({
templates: {
template: {
properties: {
backgroundColor: 'transparent'
},
childTemplates: [{
type: 'Ti.UI.Label',
bindId: 'label',
properties: {
left: 10,
color: 'black'
}
}]
}
},
backgroundColor: "#b3b3b3",
defaultItemTemplate: 'template',
sections: sections
});
win.add(listView);
win.open();
The result is the same: the scrollable child views won't appear.
If I'm not using the array and use sv.addView(insideView)
inside the loop it works fine! If I compare both UIs in Android Studio I can see that the childviews are not added:
using views = array
!no_childviews.png|thumbnail!
using addView
!childviews.png|thumbnail!
*Setup:*
* Android 11/Pixel 4
* Titanium SDK 10.1.0/10.0.0.GA
Attachments
File | Date | Size |
---|---|---|
childviews.png | 2021-05-20T11:41:41.000+0000 | 134489 |
no_childviews.png | 2021-05-20T11:41:41.000+0000 | 94525 |
ScrollableViewAddRemoveTest.js | 2021-05-26T00:09:01.000+0000 | 3040 |
I'm currently debugging TiUIScrollableView.java to see if there is something wrong in the setViews code
Turns out that calling addView after the loop:
will make it work. And running
Alloy.Collections.contacts.fetch();
in the Alloy example after the ListView is visible works, too. Might be some timing issue somewhere This is some debug output when using Alloy.Collection.fetch(): {noformat} Proxy: views property <--- setViews() from ScrollableViewProxy process properties; views len: 0 clear views set views; len: 0 Proxy: handle message clear views set views; len: 2 Proxy: views property <--- setViews() from ScrollableViewProxy Proxy: handle message clear views set views; len: 2 release list <---- release() from TiUIScrollableView process properties; views len: 0 clear views set views; len: 0 {noformat} I have two elements in my collection so len:2 is correct. I'm not sure why the wholesetViews
from ScrollableViewProxy is called twice! Then there is therelease
part from TiUIScrollableView at the bottom that is clearing the content at the end.I haven't dived into this yet, but I'm wondering if it has something to do with us "updating" the HeaderView's activity object if it doesn't match the ListView's assigned activity object. We do this as of Titanium 10.0.0 so that dark/light theme switching will be applied to all child views which involves swapping out the old destroyed activity context with the new one. https://github.com/appcelerator/titanium_mobile/blob/master/android/modules/ui/src/java/ti/modules/titanium/ui/widget/listview/ListViewHolder.java#L302-L307 I'm "guessing" that the ScrollableView or its children were initially assigned a different activity context. Like the previous activity window such as the splash and it's being swapped out immediately once the actual activity window that's hosting the ListView has been created/opened.
Your guess looks like the right direction: I've added
and got: {noformat} Context: org.appcelerator.titanium.TiActivity@92c8bbb headerproxy act:com.miga.random.TestAppActivity@af14391 release views release list process properties; views len: 0 clear views set views; len: 0 {noformat} This is AFTER the first the setViews part.
master: https://github.com/appcelerator/titanium_mobile/pull/12839
merged to master
10_0_X backport merged