The unloaded event of view in the ListView's itemTemplate will now be called when its underlying native view is removed from the visual tree. When this happens is beyond our control.

This commit is contained in:
Rossen Hristov
2015-07-20 09:13:32 +03:00
parent a4d879f5bb
commit ac36729cb7
9 changed files with 199 additions and 1 deletions

View File

@@ -78,6 +78,9 @@
</TypeScriptCompile>
<TypeScriptCompile Include="apps\action-bar-demo\pages\data-binding.ts">
<DependentUpon>data-binding.xml</DependentUpon>
<TypeScriptCompile Include="apps\list-view-demo\app.ts" />
<TypeScriptCompile Include="apps\list-view-demo\main-page.ts">
<DependentUpon>main-page.xml</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="apps\cuteness.unoptimized\app.ts" />
<TypeScriptCompile Include="apps\cuteness.unoptimized\details-page.ts">
@@ -94,6 +97,12 @@
<Content Include="apps\action-bar-demo\pages\center-view-segmented.xml" />
<Content Include="apps\action-bar-demo\pages\center-view.xml" />
<Content Include="apps\action-bar-demo\pages\data-binding.xml" />
<Content Include="apps\list-view-demo\another-page.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="apps\list-view-demo\main-page.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="apps\cuteness.unoptimized\reddit-item-view-model.ts" />
<TypeScriptCompile Include="apps\cuteness.unoptimized\reddit-model.d.ts" />
<TypeScriptCompile Include="apps\action-bar-demo\app.ts" />
@@ -1675,6 +1684,9 @@
<Content Include="apps\action-bar-demo\package.json" />
<Content Include="fetch\package.json" />
<Content Include="fetch\README.md" />
<Content Include="apps\list-view-demo\package.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="js-libs\esprima\LICENSE.BSD" />
<Content Include="source-control.md" />
<Content Include="ui\segmented-bar\package.json">

View File

@@ -0,0 +1,3 @@
<Page xmlns="http://www.nativescript.org/tns.xsd">
<Label text="Another page"/>
</Page>

View File

@@ -0,0 +1,3 @@
import application = require("application");
application.mainModule = "main-page";
application.start();

View File

@@ -0,0 +1,87 @@
import frame = require("ui/frame");
import observableArray = require("data/observable-array");
var loaded = 0;
var unloaded = 0;
var listView;
var textField;
export function onNavigatedTo(args) {
print();
}
export function onTextFieldLoaded(args) {
textField = args.object;
}
export function onListViewLoaded(args) {
listView = args.object;
console.log("ListView LOADED.");
print();
onBind();
}
export function onListViewUnloaded(args) {
console.log("ListView UNLOADED.");
print();
}
export function onBind() {
var length = textField.text;
console.log("Bind to " + length + " items");
var items = new observableArray.ObservableArray<string>();
var i = 0;
for (; i < length; i++) {
items.push("Item " + i);
}
listView.items = items;
print();
}
export function onAdd() {
var length = textField.text;
console.log("Add " + length + " items");
var i = 0;
for (; i < length; i++) {
var newItem = "Item " + (<observableArray.ObservableArray<string>>listView.items).length;
(<observableArray.ObservableArray<string>>listView.items).push(newItem);
}
print();
}
export function onRemove(s) {
var length = textField.text;
console.log("Remove " + length + " items");
var i = 0;
for (; i < length; i++) {
(<observableArray.ObservableArray<string>>listView.items).splice((<observableArray.ObservableArray<string>>listView.items).length - 1);
}
print();
}
export function onRefresh() {
console.log("Refresh");
listView.refresh();
print();
}
export function onNavigate() {
console.log("Navigate");
frame.topmost().navigate({ moduleName: "./another-page" });
print();
}
export function onViewLoaded(args) {
loaded++;
console.log(args.object.id + args.object._domId + " LOADED");
}
export function onViewUnloaded(args) {
unloaded++;
console.log(args.object.id + args.object._domId + " UNLOADED");
}
export function print() {
console.log("L/U: " + loaded + "/" + unloaded);
}

View File

@@ -0,0 +1,15 @@
<Page xmlns="http://www.nativescript.org/tns.xsd" navigatedTo="onNavigatedTo">
<StackLayout>
<TextField text="1" loaded="onTextFieldLoaded"/>
<Button text="Bind" tap="onBind"/>
<Button text="Add" tap="onAdd"/>
<Button text="Remove" tap="onRemove"/>
<Button text="Refresh" tap="onRefresh"/>
<Button text="Navigate" tap="onNavigate"/>
<ListView loaded="onListViewLoaded" unloaded="onListViewUnloaded">
<ListView.itemTemplate>
<Label text="{{ $value }}" id="label" loaded="onViewLoaded" unloaded="onViewUnloaded" />
</ListView.itemTemplate>
</ListView>
</StackLayout>
</Page>

View File

@@ -0,0 +1,2 @@
{ "name" : "list-view-demo",
"main" : "app.js" }

View File

@@ -684,3 +684,43 @@ function performNativeItemTap(listView: listViewModule.ListView, index: number):
throw new Error("Cannot perform native item tap");
}
}
//export function test_LoadedUnloaded() {
// var listView = new listViewModule.ListView();
// var vm = {
// loadedCount: 0,
// unloadedCount: 0,
// onViewLoaded: function onViewLoaded(args) {
// this.loadedCount++;
// console.log(args.object._domId + " LOADED");
// },
// onViewUnloaded: function onViewUnloaded(args) {
// this.unloadedCount++;
// console.log(args.object._domId + " UNLOADED");
// }
// };
// listView.itemTemplate = "<Label text=\"{{ $value }}\" loaded=\"{{ onViewLoaded }}\" unloaded=\"{{ onViewUnloaded }}\"/>";
// listView.bindingContext = vm;
// var count = 10;
// var modifier = listView.ios ? 1 : 0; // iOS has one fake measure cell that raises loaded.
// var generate = function (count: number): observableArray.ObservableArray<string> {
// var items = new observableArray.ObservableArray<string>();
// for (var i = 0; i < count; i++) {
// items.push("Item " + i);
// }
// return items;
// }
// function testAction(views: Array<viewModule.View>) {
// listView.items = generate(count);
// TKUnit.wait(ASYNC);
// frame.topmost().navigate("pages/navigation/pageB");
// TKUnit.wait(ASYNC);
// frame.topmost().goBack();
// TKUnit.assertEqual(vm.loadedCount, count + modifier, "Loaded Count");
// TKUnit.assertEqual(vm.unloadedCount, count, "Unloaded Count");
// }
// helper.buildUIAndRunTest(listView, testAction);
//}

View File

@@ -36,6 +36,7 @@ export class ListView extends common.ListView {
private _android: android.widget.ListView;
public _realizedItems = {};
private _androidViewId: number;
public _attachStateChangeListener: android.view.View.OnAttachStateChangeListener;
public _createUI() {
this._android = new android.widget.ListView(this._context);
@@ -90,6 +91,28 @@ export class ListView extends common.ListView {
}
}
}));
this._attachStateChangeListener = new android.view.View.OnAttachStateChangeListener({
get owner() {
return that.get();
},
onViewAttachedToWindow: function (view: android.view.View) {
//
},
onViewDetachedFromWindow: function (androidView: android.view.View) {
var owner = that.get();
if (!owner) {
return;
}
var view: viewModule.View = this.owner._realizedItems[androidView.hashCode()];
if (!view) {
return;
}
view.onUnloaded();
}
});
}
get android(): android.widget.ListView {
@@ -213,6 +236,10 @@ class ListViewAdapter extends android.widget.BaseAdapter {
}
}
if (!this._listView._realizedItems[convertView.hashCode()]) {
convertView.addOnAttachStateChangeListener(this._listView._attachStateChangeListener);
}
this._listView._realizedItems[convertView.hashCode()] = args.view;
// cache the realized index (used to raise the ItemLoading event upon scroll stop)
args.view[REALIZED_INDEX] = index;
@@ -222,4 +249,5 @@ class ListViewAdapter extends android.widget.BaseAdapter {
return convertView;
}
}
}

View File

@@ -23,6 +23,14 @@ class ListViewCell extends UITableViewCell {
static new(): ListViewCell {
return <ListViewCell>super.new();
}
public removeFromSuperview(): void {
super.removeFromSuperview();
var view: view.View = (<any>this).view;
if (view) {
view.onUnloaded();
}
}
}
function notifyForItemAtIndex(listView: definition.ListView, cell: any, eventName: string, indexPath: NSIndexPath) {