mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 20:11:24 +08:00
list-view progress
This commit is contained in:

committed by
Hristo Hristov

parent
d795ee94e4
commit
0f45a0df5e
7
tns-core-modules/ui/core/view.d.ts
vendored
7
tns-core-modules/ui/core/view.d.ts
vendored
@ -329,6 +329,11 @@ declare module "ui/core/view" {
|
||||
cssClasses: Set<string>;
|
||||
cssPseudoClasses: Set<string>;
|
||||
|
||||
/**
|
||||
* Gets the parent view. This property is read-only.
|
||||
*/
|
||||
public parent: View;
|
||||
|
||||
/**
|
||||
* Gets owner page. This is a read-only property.
|
||||
*/
|
||||
@ -776,7 +781,7 @@ declare module "ui/core/view" {
|
||||
export const fontFamilyProperty: InheritedCssProperty<Style, string>;
|
||||
export const fontStyleProperty: InheritedCssProperty<Style, string>;
|
||||
export const fontWeightProperty: InheritedCssProperty<Style, string>;
|
||||
|
||||
|
||||
export const backgroundInternalProperty: CssProperty<Style, Background>;
|
||||
export const fontInternalProperty: InheritedCssProperty<Style, Font>;
|
||||
}
|
@ -1,224 +1,72 @@
|
||||
import observable = require("data/observable");
|
||||
import view = require("ui/core/view");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import definition = require("ui/list-view");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import color = require("color");
|
||||
import * as builderModule from "ui/builder";
|
||||
import * as labelModule from "ui/label";
|
||||
import * as observableArrayModule from "data/observable-array";
|
||||
import * as weakEventsModule from "ui/core/weak-event-listener";
|
||||
import {isString, isFunction} from "utils/types";
|
||||
import { ListView as ListViewDefinition, ItemsSource } from "ui/list-view";
|
||||
import { EventData, Observable } from "data/observable";
|
||||
import { View, Template, KeyedTemplate } from "ui/core/view";
|
||||
import { Property } from "ui/core/properties";
|
||||
import { Color } from "color";
|
||||
|
||||
import { parse, parseMultipleTemplates } from "ui/builder";
|
||||
import { Label } from "ui/label";
|
||||
import { ObservableArray } from "data/observable-array";
|
||||
import { addWeakEventListener, removeWeakEventListener } from "ui/core/weak-event-listener";
|
||||
import { Bindable } from "ui/core/bindable";
|
||||
|
||||
var builder: typeof builderModule;
|
||||
function ensureBuilder() {
|
||||
if (!builder) {
|
||||
builder = require("ui/builder");
|
||||
}
|
||||
}
|
||||
|
||||
var label: typeof labelModule;
|
||||
function ensureLabel() {
|
||||
if (!label) {
|
||||
label = require("ui/label");
|
||||
}
|
||||
}
|
||||
|
||||
var observableArray: typeof observableArrayModule;
|
||||
function ensureObservableArray() {
|
||||
if (!observableArray) {
|
||||
observableArray = require("data/observable-array");
|
||||
}
|
||||
}
|
||||
|
||||
var weakEvents: typeof weakEventsModule;
|
||||
function ensureWeakEvents() {
|
||||
if (!weakEvents) {
|
||||
weakEvents = require("ui/core/weak-event-listener");
|
||||
}
|
||||
}
|
||||
|
||||
var ITEMS = "items";
|
||||
var ITEMTEMPLATE = "itemTemplate";
|
||||
var ITEMTEMPLATES = "itemTemplates";
|
||||
var ISSCROLLING = "isScrolling";
|
||||
var LISTVIEW = "ListView";
|
||||
var SEPARATORCOLOR = "separatorColor";
|
||||
var ROWHEIGHT = "rowHeight";
|
||||
|
||||
// TODO: Think of a way to register these instead of relying on hardcoded values.
|
||||
export module knownTemplates {
|
||||
export var itemTemplate = "itemTemplate";
|
||||
export let itemTemplate = "itemTemplate";
|
||||
}
|
||||
|
||||
export module knownMultiTemplates {
|
||||
export var itemTemplates = "itemTemplates";
|
||||
export let itemTemplates = "itemTemplates";
|
||||
}
|
||||
|
||||
function onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var listView = <ListView>data.object;
|
||||
listView._onItemsPropertyChanged(data);
|
||||
}
|
||||
|
||||
function onItemTemplatePropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var listView = <definition.ListView>data.object;
|
||||
listView.refresh();
|
||||
}
|
||||
|
||||
function onItemTemplatesPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var listView = <ListView>data.object;
|
||||
listView._onItemTemplatesPropertyChanged(data);
|
||||
}
|
||||
|
||||
function onRowHeightPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
var listView = <ListView>data.object;
|
||||
listView._onRowHeightPropertyChanged(data);
|
||||
}
|
||||
|
||||
export class ListView extends view.View implements definition.ListView {
|
||||
export abstract class ListViewBase extends View implements ListViewDefinition {
|
||||
public static itemLoadingEvent = "itemLoading";
|
||||
public static itemTapEvent = "itemTap";
|
||||
public static loadMoreItemsEvent = "loadMoreItems";
|
||||
// TODO: get rid of such hacks.
|
||||
public static knownFunctions = ["itemTemplateSelector"]; //See component-builder.ts isKnownFunction
|
||||
|
||||
|
||||
private _itemTemplateSelector: (item: any, index: number, items: any) => string;
|
||||
private _itemTemplateSelectorBindable = new Bindable();
|
||||
public _defaultTemplate: view.KeyedTemplate = {
|
||||
public _defaultTemplate: KeyedTemplate = {
|
||||
key: "default",
|
||||
createView: () => {
|
||||
if (this.itemTemplate) {
|
||||
ensureBuilder();
|
||||
return builder.parse(this.itemTemplate, this);
|
||||
return parse(this.itemTemplate, this);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
public _itemTemplatesInternal = new Array<view.KeyedTemplate>(this._defaultTemplate);
|
||||
|
||||
public static separatorColorProperty = new dependencyObservable.Property(
|
||||
SEPARATORCOLOR,
|
||||
LISTVIEW,
|
||||
new proxy.PropertyMetadata(undefined));
|
||||
public _itemTemplatesInternal = new Array<KeyedTemplate>(this._defaultTemplate);
|
||||
|
||||
public static itemsProperty = new dependencyObservable.Property(
|
||||
ITEMS,
|
||||
LISTVIEW,
|
||||
new proxy.PropertyMetadata(
|
||||
undefined,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
onItemsPropertyChanged
|
||||
)
|
||||
);
|
||||
|
||||
public static itemTemplateProperty = new dependencyObservable.Property(
|
||||
ITEMTEMPLATE,
|
||||
LISTVIEW,
|
||||
new proxy.PropertyMetadata(
|
||||
undefined,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
onItemTemplatePropertyChanged
|
||||
)
|
||||
);
|
||||
|
||||
public static itemTemplatesProperty = new dependencyObservable.Property(
|
||||
ITEMTEMPLATES,
|
||||
LISTVIEW,
|
||||
new proxy.PropertyMetadata(
|
||||
undefined,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
onItemTemplatesPropertyChanged
|
||||
)
|
||||
);
|
||||
|
||||
public static isScrollingProperty = new dependencyObservable.Property(
|
||||
ISSCROLLING,
|
||||
LISTVIEW,
|
||||
new proxy.PropertyMetadata(
|
||||
false,
|
||||
dependencyObservable.PropertyMetadataSettings.None
|
||||
)
|
||||
);
|
||||
|
||||
public static rowHeightProperty = new dependencyObservable.Property(
|
||||
ROWHEIGHT,
|
||||
LISTVIEW,
|
||||
new proxy.PropertyMetadata(
|
||||
-1,
|
||||
dependencyObservable.PropertyMetadataSettings.AffectsLayout,
|
||||
onRowHeightPropertyChanged
|
||||
)
|
||||
);
|
||||
|
||||
get items(): any {
|
||||
return this._getValue(ListView.itemsProperty);
|
||||
}
|
||||
set items(value: any) {
|
||||
this._setValue(ListView.itemsProperty, value);
|
||||
}
|
||||
|
||||
get itemTemplate(): string | view.Template {
|
||||
return this._getValue(ListView.itemTemplateProperty);
|
||||
}
|
||||
set itemTemplate(value: string | view.Template) {
|
||||
this._setValue(ListView.itemTemplateProperty, value);
|
||||
}
|
||||
|
||||
get itemTemplates(): string | Array<view.KeyedTemplate> {
|
||||
return this._getValue(ListView.itemTemplatesProperty);
|
||||
}
|
||||
set itemTemplates(value: string | Array<view.KeyedTemplate>) {
|
||||
let newValue = value;
|
||||
if (isString(newValue)){
|
||||
ensureBuilder();
|
||||
newValue = builder.parseMultipleTemplates(<string>newValue, this);
|
||||
}
|
||||
this._setValue(ListView.itemTemplatesProperty, newValue);
|
||||
}
|
||||
public rowHeight: number;
|
||||
public separatorColor: Color;
|
||||
public items: any[] | ItemsSource;
|
||||
public itemTemplate: string | Template;
|
||||
public itemTemplates: string | Array<KeyedTemplate>;
|
||||
|
||||
get itemTemplateSelector(): string | ((item: any, index: number, items: any) => string) {
|
||||
return this._itemTemplateSelector;
|
||||
}
|
||||
|
||||
set itemTemplateSelector(value: string | ((item: any, index: number, items: any) => string)) {
|
||||
if (isString(value)){
|
||||
if (typeof value === "string") {
|
||||
this._itemTemplateSelectorBindable.bind({
|
||||
sourceProperty: null,
|
||||
targetProperty: "templateKey",
|
||||
expression: <string>value
|
||||
expression: value
|
||||
});
|
||||
this._itemTemplateSelector = (item: any, index: number, items: any) => {
|
||||
item["$index"] = index;
|
||||
this._itemTemplateSelectorBindable.bindingContext = item;
|
||||
return this._itemTemplateSelectorBindable.get("templateKey");
|
||||
return this._itemTemplateSelectorBindable.get("templateKey");
|
||||
};
|
||||
}
|
||||
else if (isFunction(value)) {
|
||||
this._itemTemplateSelector = <((item: any, index: number, items: any) => string)>value;
|
||||
else if (typeof value === "function") {
|
||||
this._itemTemplateSelector = value;
|
||||
}
|
||||
}
|
||||
|
||||
get isScrolling(): boolean {
|
||||
return false;
|
||||
}
|
||||
set isScrolling(value: boolean) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
get separatorColor(): color.Color {
|
||||
return this.style._getValue(ListView.separatorColorProperty);
|
||||
}
|
||||
set separatorColor(value: color.Color) {
|
||||
this.style._setValue(ListView.separatorColorProperty,
|
||||
value instanceof color.Color ? value : new color.Color(<any>value));
|
||||
}
|
||||
|
||||
get rowHeight(): number {
|
||||
return this._getValue(ListView.rowHeightProperty);
|
||||
}
|
||||
set rowHeight(value: number) {
|
||||
this._setValue(ListView.rowHeightProperty, value);
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
//
|
||||
}
|
||||
@ -227,69 +75,107 @@ export class ListView extends view.View implements definition.ListView {
|
||||
//
|
||||
}
|
||||
|
||||
public _getItemTemplate(index: number): view.KeyedTemplate {
|
||||
public _getItemTemplate(index: number): KeyedTemplate {
|
||||
let templateKey = "default";
|
||||
if (this.itemTemplateSelector){
|
||||
if (this.itemTemplateSelector) {
|
||||
let dataItem = this._getDataItem(index);
|
||||
templateKey = this._itemTemplateSelector(dataItem, index, this.items);
|
||||
}
|
||||
|
||||
for (let i = 0, length = this._itemTemplatesInternal.length; i < length; i++) {
|
||||
if (this._itemTemplatesInternal[i].key === templateKey){
|
||||
if (this._itemTemplatesInternal[i].key === templateKey) {
|
||||
return this._itemTemplatesInternal[i];
|
||||
}
|
||||
}
|
||||
|
||||
// This is the default template
|
||||
return this._itemTemplatesInternal[0];
|
||||
return this._itemTemplatesInternal[0];
|
||||
}
|
||||
|
||||
public _prepareItem(item: view.View, index: number) {
|
||||
|
||||
public _prepareItem(item: View, index: number) {
|
||||
if (item) {
|
||||
item.bindingContext = this._getDataItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
private _getDataItem(index: number): any {
|
||||
let thisItems = this.items;
|
||||
let thisItems = <ItemsSource>this.items;
|
||||
return thisItems.getItem ? thisItems.getItem(index) : thisItems[index];
|
||||
}
|
||||
|
||||
public _getDefaultItemContent(index: number): view.View {
|
||||
ensureLabel();
|
||||
|
||||
var lbl = new label.Label();
|
||||
public _getDefaultItemContent(index: number): View {
|
||||
let lbl = new Label();
|
||||
lbl.bind({
|
||||
targetProperty: "text",
|
||||
sourceProperty: "$value"
|
||||
});
|
||||
}, null);
|
||||
return lbl;
|
||||
}
|
||||
|
||||
public _onItemsPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
ensureObservableArray();
|
||||
ensureWeakEvents();
|
||||
public _onItemsChanged(args: EventData) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
if (data.oldValue instanceof observable.Observable) {
|
||||
weakEvents.removeWeakEventListener(data.oldValue, observableArray.ObservableArray.changeEvent, this._onItemsChanged, this);
|
||||
public _onRowHeightPropertyChanged(oldValue: number, newValue: number) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the property backing the items property of each ListView instance.
|
||||
*/
|
||||
export const itemsProperty = new Property<ListViewBase, any[] | ItemsSource>({
|
||||
name: "items", valueChanged: (target, oldValue, newValue) => {
|
||||
if (oldValue instanceof Observable) {
|
||||
removeWeakEventListener(oldValue, ObservableArray.changeEvent, target._onItemsChanged, target);
|
||||
}
|
||||
|
||||
if (data.newValue instanceof observable.Observable) {
|
||||
weakEvents.addWeakEventListener(data.newValue, observableArray.ObservableArray.changeEvent, this._onItemsChanged, this);
|
||||
if (newValue instanceof Observable) {
|
||||
addWeakEventListener(newValue, ObservableArray.changeEvent, target._onItemsChanged, target);
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
target.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
private _onItemsChanged(args: observable.EventData) {
|
||||
this.refresh();
|
||||
/**
|
||||
* Represents the item template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplateProperty = new Property<ListViewBase, string | Template>({
|
||||
name: "itemTemplate", valueChanged: (target) => {
|
||||
target.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
public _onRowHeightPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
this.refresh();
|
||||
}
|
||||
/**
|
||||
* Represents the items template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplatesProperty = new Property<ListViewBase, string | Array<KeyedTemplate>>({
|
||||
name: "itemTemplates", valueConverter: (value) => {
|
||||
if (typeof value === "string") {
|
||||
return parseMultipleTemplates(value);
|
||||
}
|
||||
|
||||
public _onItemTemplatesPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
//
|
||||
return value;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Represents the separator color backing property.
|
||||
*/
|
||||
export const separatorColor = new Property<ListViewBase, Color>({
|
||||
name: "separatorColor", valueConverter: (value) => {
|
||||
if (typeof value === "string") {
|
||||
return new Color(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the rowHeight property of each ListView instance.
|
||||
*/
|
||||
export const rowHeightProperty = new Property<ListViewBase, number>({
|
||||
name: "rowHeight", defaultValue: -1, valueChanged: (target, oldValue, newValue) => target._onRowHeightPropertyChanged(oldValue, newValue)
|
||||
});
|
||||
|
@ -1,50 +1,41 @@
|
||||
import observable = require("data/observable");
|
||||
import common = require("./list-view-common");
|
||||
import viewModule = require("ui/core/view");
|
||||
import stackLayout = require("ui/layouts/stack-layout");
|
||||
import proxy = require("ui/core/proxy");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import definition = require("ui/list-view");
|
||||
import {ProxyViewContainer} from "ui/proxy-view-container";
|
||||
import * as layoutBase from "ui/layouts/layout-base";
|
||||
import * as colorModule from "color";
|
||||
import { separatorColorProperty, registerHandler, Styler, StylePropertyChangedHandler } from "ui/styling/style";
|
||||
import { ItemEventData, ItemsSource } from "ui/list-view";
|
||||
import { ListViewBase, separatorColor, itemTemplatesProperty } from "./list-view-common";
|
||||
import { View, KeyedTemplate } from "ui/core/view";
|
||||
import { Property } from "ui/core/properties";
|
||||
import { unsetValue } from "ui/core/dependency-observable";
|
||||
import { Observable } from "data/observable";
|
||||
import { StackLayout } from "ui/layouts/stack-layout";
|
||||
import { ProxyViewContainer } from "ui/proxy-view-container";
|
||||
import { LayoutBase } from "ui/layouts/layout-base";
|
||||
import { Color } from "color";
|
||||
|
||||
let color: typeof colorModule;
|
||||
function ensureColor() {
|
||||
if (!color) {
|
||||
color = require("color");
|
||||
export * from "./list-view-common";
|
||||
|
||||
let ITEMLOADING = ListViewBase.itemLoadingEvent;
|
||||
let LOADMOREITEMS = ListViewBase.loadMoreItemsEvent;
|
||||
let ITEMTAP = ListViewBase.itemTapEvent;
|
||||
|
||||
@Interfaces([])
|
||||
class ItemClickListener implements android.widget.AdapterView.OnItemClickListener {
|
||||
constructor(private owner: WeakRef<ListView>) {
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
onItemClick<T extends android.widget.Adapter>(parent: android.widget.AdapterView<T>, convertView: android.view.View, index: number, id: number) {
|
||||
let owner = this.owner.get();
|
||||
if (owner) {
|
||||
let view = owner._realizedTemplates.get(owner._getItemTemplate(index).key).get(convertView);
|
||||
owner.notify({ eventName: ITEMTAP, object: owner, index: index, view: view });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let ITEMLOADING = common.ListView.itemLoadingEvent;
|
||||
let LOADMOREITEMS = common.ListView.loadMoreItemsEvent;
|
||||
let ITEMTAP = common.ListView.itemTapEvent;
|
||||
|
||||
global.moduleMerge(common, exports);
|
||||
|
||||
function onSeparatorColorPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
let listView = <ListView>data.object;
|
||||
if (!listView.android) {
|
||||
return;
|
||||
}
|
||||
|
||||
ensureColor();
|
||||
|
||||
if (data.newValue instanceof color.Color) {
|
||||
listView.android.setDivider(new android.graphics.drawable.ColorDrawable(data.newValue.android));
|
||||
listView.android.setDividerHeight(1);
|
||||
}
|
||||
}
|
||||
|
||||
// register the setNativeValue callbacks
|
||||
(<proxy.PropertyMetadata>common.ListView.separatorColorProperty.metadata).onSetNativeValue = onSeparatorColorPropertyChanged;
|
||||
|
||||
export class ListView extends common.ListView {
|
||||
export class ListView extends ListViewBase {
|
||||
private _androidViewId: number = -1;
|
||||
private _android: android.widget.ListView;
|
||||
public _realizedItems = new Map<android.view.View, viewModule.View>();
|
||||
public _realizedTemplates = new Map<string, Map<android.view.View, viewModule.View>>();
|
||||
private _itemClickListener: android.widget.AdapterView.OnItemClickListener;
|
||||
public _realizedItems = new Map<android.view.View, View>();
|
||||
public _realizedTemplates = new Map<string, Map<android.view.View, View>>();
|
||||
|
||||
public _createUI() {
|
||||
this._android = new android.widget.ListView(this._context);
|
||||
@ -61,15 +52,8 @@ export class ListView extends common.ListView {
|
||||
this.android.setAdapter(new ListViewAdapterClass(this));
|
||||
|
||||
let that = new WeakRef(this);
|
||||
this.android.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener({
|
||||
onItemClick: function (parent: any, convertView: android.view.View, index: number, id: number) {
|
||||
let owner = that.get();
|
||||
if (owner) {
|
||||
let view = owner._realizedTemplates.get(owner._getItemTemplate(index).key).get(convertView);
|
||||
owner.notify({ eventName: ITEMTAP, object: owner, index: index, view: view });
|
||||
}
|
||||
}
|
||||
}));
|
||||
this._itemClickListener = this._itemClickListener || new ItemClickListener(new WeakRef(this));
|
||||
this.android.setOnItemClickListener(this._itemClickListener);
|
||||
}
|
||||
|
||||
get android(): android.widget.ListView {
|
||||
@ -82,12 +66,12 @@ export class ListView extends common.ListView {
|
||||
}
|
||||
|
||||
// clear bindingContext when it is not observable because otherwise bindings to items won't reevaluate
|
||||
this._realizedItems.forEach((view, nativeView, map) => {
|
||||
if (!(view.bindingContext instanceof observable.Observable)) {
|
||||
this._realizedItems.forEach((view, nativeView, map) => {
|
||||
if (!(view.bindingContext instanceof Observable)) {
|
||||
view.bindingContext = null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
(<android.widget.BaseAdapter>this.android.getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@ -106,7 +90,7 @@ export class ListView extends common.ListView {
|
||||
return this._realizedItems.size;
|
||||
}
|
||||
|
||||
public _eachChildView(callback: (child: viewModule.View) => boolean): void {
|
||||
public _eachChildView(callback: (child: View) => boolean): void {
|
||||
this._realizedItems.forEach((view, nativeView, map) => {
|
||||
if (view.parent instanceof ListView) {
|
||||
callback(view);
|
||||
@ -120,16 +104,16 @@ export class ListView extends common.ListView {
|
||||
});
|
||||
}
|
||||
|
||||
public _dumpRealizedTemplates(){
|
||||
console.log(`Realized Templates:`);
|
||||
public _dumpRealizedTemplates() {
|
||||
console.log(`Realized Templates:`);
|
||||
this._realizedTemplates.forEach((value, index, map) => {
|
||||
console.log(`\t${index}:`);
|
||||
value.forEach((value, index, map) => {
|
||||
console.log(`\t\t${index.hashCode()}: ${value}`);
|
||||
});
|
||||
});
|
||||
console.log(`Realized Items Size: ${this._realizedItems.size}`);
|
||||
}
|
||||
console.log(`Realized Items Size: ${this._realizedItems.size}`);
|
||||
}
|
||||
|
||||
private clearRealizedCells(): void {
|
||||
// clear the cache
|
||||
@ -147,17 +131,30 @@ export class ListView extends common.ListView {
|
||||
this._realizedTemplates.clear();
|
||||
}
|
||||
|
||||
public _onItemTemplatesPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
this._itemTemplatesInternal = new Array<viewModule.KeyedTemplate>(this._defaultTemplate);
|
||||
if (data.newValue){
|
||||
this._itemTemplatesInternal = this._itemTemplatesInternal.concat(data.newValue);
|
||||
get [separatorColor.native](): number {
|
||||
return null;
|
||||
}
|
||||
set [separatorColor.native](value: Color) {
|
||||
let nativeView = this._android;
|
||||
if (value) {
|
||||
nativeView.setDivider(new android.graphics.drawable.ColorDrawable(value.android));
|
||||
nativeView.setDividerHeight(1);
|
||||
} else {
|
||||
nativeView.setDivider(null);
|
||||
nativeView.setDividerHeight(0);
|
||||
}
|
||||
|
||||
if (this.android){
|
||||
ensureListViewAdapterClass();
|
||||
this.android.setAdapter(new ListViewAdapterClass(this));
|
||||
}
|
||||
|
||||
get [itemTemplatesProperty.native](): KeyedTemplate[] {
|
||||
return null;
|
||||
}
|
||||
set [itemTemplatesProperty.native](value: KeyedTemplate[]) {
|
||||
this._itemTemplatesInternal = new Array<KeyedTemplate>(this._defaultTemplate);
|
||||
if (value) {
|
||||
this._itemTemplatesInternal = this._itemTemplatesInternal.concat(value);
|
||||
}
|
||||
|
||||
|
||||
this.android.setAdapter(new ListViewAdapterClass(this));
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
@ -173,9 +170,7 @@ function ensureListViewAdapterClass() {
|
||||
|
||||
constructor(listView: ListView) {
|
||||
super();
|
||||
|
||||
this._listView = listView;
|
||||
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
@ -185,7 +180,8 @@ function ensureListViewAdapterClass() {
|
||||
|
||||
public getItem(i: number) {
|
||||
if (this._listView && this._listView.items && i < this._listView.items.length) {
|
||||
return this._listView.items.getItem ? this._listView.items.getItem(i) : this._listView.items[i];
|
||||
let getItem = (<ItemsSource>this._listView.items).getItem
|
||||
return getItem ? getItem(i) : this._listView.items[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -200,7 +196,7 @@ function ensureListViewAdapterClass() {
|
||||
}
|
||||
|
||||
public getViewTypeCount() {
|
||||
return this._listView._itemTemplatesInternal.length;
|
||||
return this._listView._itemTemplatesInternal.length;
|
||||
}
|
||||
|
||||
public getItemViewType(index: number) {
|
||||
@ -208,10 +204,10 @@ function ensureListViewAdapterClass() {
|
||||
let itemViewType = this._listView._itemTemplatesInternal.indexOf(template);
|
||||
return itemViewType;
|
||||
}
|
||||
|
||||
|
||||
public getView(index: number, convertView: android.view.View, parent: android.view.ViewGroup): android.view.View {
|
||||
//this._listView._dumpRealizedTemplates();
|
||||
|
||||
|
||||
if (!this._listView) {
|
||||
return null;
|
||||
}
|
||||
@ -223,10 +219,10 @@ function ensureListViewAdapterClass() {
|
||||
|
||||
// Recycle an existing view or create a new one if needed.
|
||||
let template = this._listView._getItemTemplate(index);
|
||||
let view: viewModule.View;
|
||||
if (convertView){
|
||||
let view: View;
|
||||
if (convertView) {
|
||||
view = this._listView._realizedTemplates.get(template.key).get(convertView);
|
||||
if (!view){
|
||||
if (!view) {
|
||||
throw new Error(`There is no entry with key '${convertView}' in the realized views cache for template with key'${template.key}'.`);
|
||||
}
|
||||
}
|
||||
@ -234,7 +230,7 @@ function ensureListViewAdapterClass() {
|
||||
view = template.createView();
|
||||
}
|
||||
|
||||
let args: definition.ItemEventData = {
|
||||
let args: ItemEventData = {
|
||||
eventName: ITEMLOADING, object: this._listView, index: index, view: view,
|
||||
android: parent,
|
||||
ios: undefined
|
||||
@ -251,19 +247,19 @@ function ensureListViewAdapterClass() {
|
||||
args.view.height = this._listView.rowHeight;
|
||||
}
|
||||
else {
|
||||
args.view.height = Number.NaN;
|
||||
args.view.height = unsetValue;
|
||||
}
|
||||
|
||||
this._listView._prepareItem(args.view, index);
|
||||
if (!args.view.parent) {
|
||||
// Proxy containers should not get treated as layouts.
|
||||
// Wrap them in a real layout as well.
|
||||
if (args.view instanceof layoutBase.LayoutBase &&
|
||||
if (args.view instanceof LayoutBase &&
|
||||
!(args.view instanceof ProxyViewContainer)) {
|
||||
this._listView._addView(args.view);
|
||||
convertView = args.view.android;
|
||||
} else {
|
||||
let sp = new stackLayout.StackLayout();
|
||||
let sp = new StackLayout();
|
||||
sp.addChild(args.view);
|
||||
this._listView._addView(sp);
|
||||
|
||||
@ -273,10 +269,10 @@ function ensureListViewAdapterClass() {
|
||||
|
||||
// Cache the view for recycling
|
||||
let realizedItemsForTemplateKey = this._listView._realizedTemplates.get(template.key);
|
||||
if (!realizedItemsForTemplateKey){
|
||||
realizedItemsForTemplateKey = new Map<android.view.View, viewModule.View>();
|
||||
if (!realizedItemsForTemplateKey) {
|
||||
realizedItemsForTemplateKey = new Map<android.view.View, View>();
|
||||
this._listView._realizedTemplates.set(template.key, realizedItemsForTemplateKey);
|
||||
}
|
||||
}
|
||||
realizedItemsForTemplateKey.set(convertView, args.view);
|
||||
this._listView._realizedItems.set(convertView, args.view);
|
||||
}
|
||||
@ -309,4 +305,4 @@ export class ListViewStyler implements Styler {
|
||||
}
|
||||
}
|
||||
|
||||
ListViewStyler.registerHandlers();
|
||||
ListViewStyler.registerHandlers();
|
||||
|
83
tns-core-modules/ui/list-view/list-view.d.ts
vendored
83
tns-core-modules/ui/list-view/list-view.d.ts
vendored
@ -2,10 +2,10 @@
|
||||
* Contains the ListView class, which represents a standard list view widget.
|
||||
*/
|
||||
declare module "ui/list-view" {
|
||||
import observable = require("data/observable");
|
||||
import dependencyObservable = require("ui/core/dependency-observable");
|
||||
import view = require("ui/core/view");
|
||||
import color = require("color");
|
||||
import { EventData } from "data/observable";
|
||||
import { View, Template, KeyedTemplate } from "ui/core/view";
|
||||
import { Property } from "ui/core/properties";
|
||||
import { Color } from "color";
|
||||
|
||||
/**
|
||||
* Known template names.
|
||||
@ -20,7 +20,7 @@ declare module "ui/list-view" {
|
||||
/**
|
||||
* Represents a view that shows items in a vertically scrolling list.
|
||||
*/
|
||||
export class ListView extends view.View {
|
||||
export class ListView extends View {
|
||||
/**
|
||||
* String value used when hooking to itemLoading event.
|
||||
*/
|
||||
@ -34,27 +34,6 @@ declare module "ui/list-view" {
|
||||
*/
|
||||
public static loadMoreItemsEvent: string;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the items property of each ListView instance.
|
||||
*/
|
||||
public static itemsProperty: dependencyObservable.Property;
|
||||
|
||||
/**
|
||||
* Represents the item template property of each ListView instance.
|
||||
*/
|
||||
public static itemTemplateProperty: dependencyObservable.Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the isScrolling property of each ListView instance.
|
||||
*/
|
||||
@Deprecated // in 2.1
|
||||
public static isScrollingProperty: dependencyObservable.Property;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the rowHeight property of each ListView instance.
|
||||
*/
|
||||
public static rowHeightProperty: dependencyObservable.Property;
|
||||
|
||||
/**
|
||||
* Gets the native [android widget](http://developer.android.com/reference/android/widget/ListView.html) that represents the user interface for this component. Valid only when running on Android OS.
|
||||
*/
|
||||
@ -65,27 +44,21 @@ declare module "ui/list-view" {
|
||||
*/
|
||||
ios: any /* UITableView */;
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the ListView is currently scrolling.
|
||||
*/
|
||||
@Deprecated // in 2.1
|
||||
isScrolling: boolean;
|
||||
|
||||
/**
|
||||
* Gets or set the items collection of the ListView.
|
||||
* The items property can be set to an array or an object defining length and getItem(index) method.
|
||||
*/
|
||||
items: any;
|
||||
items: any[] | ItemsSource;
|
||||
|
||||
/**
|
||||
* Gets or set the item template of the ListView.
|
||||
*/
|
||||
itemTemplate: string | view.Template;
|
||||
itemTemplate: string | Template;
|
||||
|
||||
/**
|
||||
* Gets or set the list of item templates for the item template selector
|
||||
*/
|
||||
itemTemplates: string | Array<view.KeyedTemplate>;
|
||||
itemTemplates: string | Array<KeyedTemplate>;
|
||||
|
||||
/**
|
||||
* A function that returns the appropriate ket template based on the data item.
|
||||
@ -95,7 +68,7 @@ declare module "ui/list-view" {
|
||||
/**
|
||||
* Gets or set the items separator line color of the ListView.
|
||||
*/
|
||||
separatorColor: color.Color;
|
||||
separatorColor: Color;
|
||||
|
||||
/**
|
||||
* Gets or set row height of the ListView.
|
||||
@ -121,7 +94,7 @@ declare module "ui/list-view" {
|
||||
* @param callback - Callback function which will be executed when event is raised.
|
||||
* @param thisArg - An optional parameter which will be used as `this` context for callback execution.
|
||||
*/
|
||||
on(eventNames: string, callback: (data: observable.EventData) => void, thisArg?: any);
|
||||
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
|
||||
|
||||
/**
|
||||
* Raised when a View for the data at the specified index should be created.
|
||||
@ -139,13 +112,13 @@ declare module "ui/list-view" {
|
||||
/**
|
||||
* Raised when the ListView is scrolled so that its last item is visible.
|
||||
*/
|
||||
on(event: "loadMoreItems", callback: (args: observable.EventData) => void, thisArg?: any);
|
||||
on(event: "loadMoreItems", callback: (args: EventData) => void, thisArg?: any);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event data containing information for the index and the view associated to a list view item.
|
||||
*/
|
||||
export interface ItemEventData extends observable.EventData {
|
||||
export interface ItemEventData extends EventData {
|
||||
/**
|
||||
* The index of the item, for which the event is raised.
|
||||
*/
|
||||
@ -154,7 +127,7 @@ declare module "ui/list-view" {
|
||||
/**
|
||||
* The view that is associated to the item, for which the event is raised.
|
||||
*/
|
||||
view: view.View;
|
||||
view: View;
|
||||
|
||||
/**
|
||||
* Gets the native [iOS view](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewCell_Class/) that represents the user interface where the view is hosted. Valid only when running on iOS.
|
||||
@ -166,4 +139,34 @@ declare module "ui/list-view" {
|
||||
*/
|
||||
android: any /* android.view.ViewGroup */;
|
||||
}
|
||||
|
||||
export interface ItemsSource {
|
||||
length: number;
|
||||
getItem(index: number): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the property backing the items property of each ListView instance.
|
||||
*/
|
||||
export const itemsProperty: Property<ListView, any[] | ItemsSource>;
|
||||
|
||||
/**
|
||||
* Represents the item template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplateProperty: Property<ListView, string | Template>;
|
||||
|
||||
/**
|
||||
* Represents the items template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplatesProperty: Property<ListView, string | Array<KeyedTemplate>>;
|
||||
|
||||
/**
|
||||
* Represents the separator color backing property.
|
||||
*/
|
||||
export const separatorColor: Property<ListView, Color>;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the rowHeight property of each ListView instance.
|
||||
*/
|
||||
export const rowHeightProperty: Property<ListView, number>;
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ export class ListView extends common.ListView {
|
||||
private _dataSource;
|
||||
private _delegate;
|
||||
private _heights: Array<number>;
|
||||
private _preparingCell: boolean = false;
|
||||
private _isDataDirty: boolean = false;
|
||||
private _preparingCell: boolean;
|
||||
private _isDataDirty: boolean;
|
||||
private _map: Map<ListViewCell, view.View>;
|
||||
public _rowHeight: number = -1;
|
||||
widthMeasureSpec: number = 0;
|
||||
@ -233,7 +233,7 @@ export class ListView extends common.ListView {
|
||||
this._map = new Map<ListViewCell, view.View>();
|
||||
}
|
||||
|
||||
public _onItemTemplatesPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
protected _onItemTemplatesPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
this._itemTemplatesInternal = new Array<view.KeyedTemplate>(this._defaultTemplate);
|
||||
if (data.newValue) {
|
||||
for(let i = 0, length = data.newValue.length; i < length; i++){
|
||||
@ -304,16 +304,16 @@ export class ListView extends common.ListView {
|
||||
this._heights[index] = value;
|
||||
}
|
||||
|
||||
public _onRowHeightPropertyChanged(data: dependencyObservable.PropertyChangeData) {
|
||||
this._rowHeight = data.newValue;
|
||||
if (data.newValue < 0) {
|
||||
public _onRowHeightPropertyChanged(oldValue: number, newValue: number) {
|
||||
this._rowHeight = newValue;
|
||||
if (newValue < 0) {
|
||||
this._nativeView.rowHeight = UITableViewAutomaticDimension;
|
||||
this._nativeView.estimatedRowHeight = DEFAULT_HEIGHT;
|
||||
this._delegate = UITableViewDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
else {
|
||||
this._nativeView.rowHeight = data.newValue;
|
||||
this._nativeView.estimatedRowHeight = data.newValue;
|
||||
this._nativeView.rowHeight = newValue;
|
||||
this._nativeView.estimatedRowHeight = newValue;
|
||||
this._delegate = UITableViewRowHeightDelegateImpl.initWithOwner(new WeakRef(this));
|
||||
}
|
||||
|
||||
@ -321,7 +321,7 @@ export class ListView extends common.ListView {
|
||||
this._nativeView.delegate = this._delegate;
|
||||
}
|
||||
|
||||
super._onRowHeightPropertyChanged(data);
|
||||
super._onRowHeightPropertyChanged(oldValue, newValue);
|
||||
}
|
||||
|
||||
public requestLayout(): void {
|
||||
|
Reference in New Issue
Block a user