mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
chore: format
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { ItemEventData, ItemsSource } from ".";
|
||||
import {
|
||||
ListViewBase,
|
||||
separatorColorProperty, itemTemplatesProperty
|
||||
ListViewBase,
|
||||
separatorColorProperty,
|
||||
itemTemplatesProperty,
|
||||
} from "./list-view-common";
|
||||
import { View, KeyedTemplate } from "../core/view";
|
||||
import { unsetValue } from "../core/properties";
|
||||
@@ -20,332 +21,392 @@ const LOADMOREITEMS = ListViewBase.loadMoreItemsEvent;
|
||||
const ITEMTAP = ListViewBase.itemTapEvent;
|
||||
|
||||
interface ItemClickListener {
|
||||
new(owner: ListView): android.widget.AdapterView.OnItemClickListener;
|
||||
new (owner: ListView): android.widget.AdapterView.OnItemClickListener;
|
||||
}
|
||||
|
||||
let ItemClickListener: ItemClickListener;
|
||||
|
||||
function initializeItemClickListener(): void {
|
||||
if (ItemClickListener) {
|
||||
return;
|
||||
}
|
||||
if (ItemClickListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Interfaces([android.widget.AdapterView.OnItemClickListener])
|
||||
class ItemClickListenerImpl extends java.lang.Object implements android.widget.AdapterView.OnItemClickListener {
|
||||
constructor(public owner: ListView) {
|
||||
super();
|
||||
@Interfaces([android.widget.AdapterView.OnItemClickListener])
|
||||
class ItemClickListenerImpl extends java.lang.Object
|
||||
implements android.widget.AdapterView.OnItemClickListener {
|
||||
constructor(public owner: ListView) {
|
||||
super();
|
||||
|
||||
return global.__native(this);
|
||||
}
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
onItemClick<T extends android.widget.Adapter>(parent: android.widget.AdapterView<T>, convertView: android.view.View, index: number, id: number) {
|
||||
const owner = this.owner;
|
||||
const view = owner._realizedTemplates.get(owner._getItemTemplate(index).key).get(convertView);
|
||||
owner.notify({ eventName: ITEMTAP, object: owner, index: index, view: view });
|
||||
}
|
||||
}
|
||||
onItemClick<T extends android.widget.Adapter>(
|
||||
parent: android.widget.AdapterView<T>,
|
||||
convertView: android.view.View,
|
||||
index: number,
|
||||
id: number
|
||||
) {
|
||||
const owner = this.owner;
|
||||
const view = owner._realizedTemplates
|
||||
.get(owner._getItemTemplate(index).key)
|
||||
.get(convertView);
|
||||
owner.notify({
|
||||
eventName: ITEMTAP,
|
||||
object: owner,
|
||||
index: index,
|
||||
view: view,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ItemClickListener = ItemClickListenerImpl;
|
||||
ItemClickListener = ItemClickListenerImpl;
|
||||
}
|
||||
|
||||
export class ListView extends ListViewBase {
|
||||
nativeViewProtected: android.widget.ListView;
|
||||
private _androidViewId: number = -1;
|
||||
nativeViewProtected: android.widget.ListView;
|
||||
private _androidViewId: number = -1;
|
||||
|
||||
public _realizedItems = new Map<android.view.View, View>();
|
||||
public _realizedTemplates = new Map<string, Map<android.view.View, View>>();
|
||||
public _realizedItems = new Map<android.view.View, View>();
|
||||
public _realizedTemplates = new Map<string, Map<android.view.View, View>>();
|
||||
|
||||
@profile()
|
||||
public createNativeView() {
|
||||
const listView = new android.widget.ListView(this._context);
|
||||
listView.setDescendantFocusability(android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS);
|
||||
@profile()
|
||||
public createNativeView() {
|
||||
const listView = new android.widget.ListView(this._context);
|
||||
listView.setDescendantFocusability(
|
||||
android.view.ViewGroup.FOCUS_AFTER_DESCENDANTS
|
||||
);
|
||||
|
||||
// Fixes issue with black random black items when scrolling
|
||||
listView.setCacheColorHint(android.graphics.Color.TRANSPARENT);
|
||||
// Fixes issue with black random black items when scrolling
|
||||
listView.setCacheColorHint(android.graphics.Color.TRANSPARENT);
|
||||
|
||||
return listView;
|
||||
}
|
||||
return listView;
|
||||
}
|
||||
|
||||
public initNativeView(): void {
|
||||
super.initNativeView();
|
||||
this.updateEffectiveRowHeight();
|
||||
public initNativeView(): void {
|
||||
super.initNativeView();
|
||||
this.updateEffectiveRowHeight();
|
||||
|
||||
const nativeView = this.nativeViewProtected;
|
||||
initializeItemClickListener();
|
||||
ensureListViewAdapterClass();
|
||||
const adapter = new ListViewAdapterClass(this);
|
||||
nativeView.setAdapter(adapter);
|
||||
(<any>nativeView).adapter = adapter;
|
||||
const nativeView = this.nativeViewProtected;
|
||||
initializeItemClickListener();
|
||||
ensureListViewAdapterClass();
|
||||
const adapter = new ListViewAdapterClass(this);
|
||||
nativeView.setAdapter(adapter);
|
||||
(<any>nativeView).adapter = adapter;
|
||||
|
||||
const itemClickListener = new ItemClickListener(this);
|
||||
nativeView.setOnItemClickListener(itemClickListener);
|
||||
(<any>nativeView).itemClickListener = itemClickListener;
|
||||
const itemClickListener = new ItemClickListener(this);
|
||||
nativeView.setOnItemClickListener(itemClickListener);
|
||||
(<any>nativeView).itemClickListener = itemClickListener;
|
||||
|
||||
if (this._androidViewId < 0) {
|
||||
this._androidViewId = android.view.View.generateViewId();
|
||||
}
|
||||
nativeView.setId(this._androidViewId);
|
||||
}
|
||||
if (this._androidViewId < 0) {
|
||||
this._androidViewId = android.view.View.generateViewId();
|
||||
}
|
||||
nativeView.setId(this._androidViewId);
|
||||
}
|
||||
|
||||
public disposeNativeView() {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
nativeView.setAdapter(null);
|
||||
(<any>nativeView).itemClickListener.owner = null;
|
||||
(<any>nativeView).adapter.owner = null;
|
||||
this.clearRealizedCells();
|
||||
super.disposeNativeView();
|
||||
}
|
||||
public disposeNativeView() {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
nativeView.setAdapter(null);
|
||||
(<any>nativeView).itemClickListener.owner = null;
|
||||
(<any>nativeView).adapter.owner = null;
|
||||
this.clearRealizedCells();
|
||||
super.disposeNativeView();
|
||||
}
|
||||
|
||||
public onLoaded() {
|
||||
super.onLoaded();
|
||||
// Without this call itemClick won't be fired... :(
|
||||
this.requestLayout();
|
||||
}
|
||||
public onLoaded() {
|
||||
super.onLoaded();
|
||||
// Without this call itemClick won't be fired... :(
|
||||
this.requestLayout();
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
if (!nativeView || !nativeView.getAdapter()) {
|
||||
return;
|
||||
}
|
||||
public refresh() {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
if (!nativeView || !nativeView.getAdapter()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear bindingContext when it is not observable because otherwise bindings to items won't reevaluate
|
||||
this._realizedItems.forEach((view, nativeView) => {
|
||||
if (!(view.bindingContext instanceof Observable)) {
|
||||
view.bindingContext = null;
|
||||
}
|
||||
});
|
||||
// clear bindingContext when it is not observable because otherwise bindings to items won't reevaluate
|
||||
this._realizedItems.forEach((view, nativeView) => {
|
||||
if (!(view.bindingContext instanceof Observable)) {
|
||||
view.bindingContext = null;
|
||||
}
|
||||
});
|
||||
|
||||
(<android.widget.BaseAdapter>nativeView.getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
(<android.widget.BaseAdapter>(
|
||||
nativeView.getAdapter()
|
||||
)).notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public scrollToIndex(index: number) {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
if (nativeView) {
|
||||
nativeView.setSelection(index);
|
||||
}
|
||||
}
|
||||
public scrollToIndex(index: number) {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
if (nativeView) {
|
||||
nativeView.setSelection(index);
|
||||
}
|
||||
}
|
||||
|
||||
public scrollToIndexAnimated(index: number) {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
if (nativeView) {
|
||||
nativeView.smoothScrollToPosition(index);
|
||||
}
|
||||
}
|
||||
public scrollToIndexAnimated(index: number) {
|
||||
const nativeView = this.nativeViewProtected;
|
||||
if (nativeView) {
|
||||
nativeView.smoothScrollToPosition(index);
|
||||
}
|
||||
}
|
||||
|
||||
get _childrenCount(): number {
|
||||
return this._realizedItems.size;
|
||||
}
|
||||
get _childrenCount(): number {
|
||||
return this._realizedItems.size;
|
||||
}
|
||||
|
||||
public eachChildView(callback: (child: View) => boolean): void {
|
||||
this._realizedItems.forEach((view, nativeView) => {
|
||||
if (view.parent instanceof ListView) {
|
||||
callback(view);
|
||||
}
|
||||
else {
|
||||
// in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined)
|
||||
if (view.parent) {
|
||||
callback(<View>view.parent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public eachChildView(callback: (child: View) => boolean): void {
|
||||
this._realizedItems.forEach((view, nativeView) => {
|
||||
if (view.parent instanceof ListView) {
|
||||
callback(view);
|
||||
} else {
|
||||
// in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined)
|
||||
if (view.parent) {
|
||||
callback(<View>view.parent);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public _dumpRealizedTemplates() {
|
||||
console.log(`Realized Templates:`);
|
||||
this._realizedTemplates.forEach((value, index) => {
|
||||
console.log(`\t${index}:`);
|
||||
value.forEach((value, index) => {
|
||||
console.log(`\t\t${index.hashCode()}: ${value}`);
|
||||
});
|
||||
});
|
||||
console.log(`Realized Items Size: ${this._realizedItems.size}`);
|
||||
}
|
||||
public _dumpRealizedTemplates() {
|
||||
console.log(`Realized Templates:`);
|
||||
this._realizedTemplates.forEach((value, index) => {
|
||||
console.log(`\t${index}:`);
|
||||
value.forEach((value, index) => {
|
||||
console.log(`\t\t${index.hashCode()}: ${value}`);
|
||||
});
|
||||
});
|
||||
console.log(`Realized Items Size: ${this._realizedItems.size}`);
|
||||
}
|
||||
|
||||
private clearRealizedCells(): void {
|
||||
// clear the cache
|
||||
this._realizedItems.forEach((view, nativeView) => {
|
||||
if (view.parent) {
|
||||
// This is to clear the StackLayout that is used to wrap non LayoutBase & ProxyViewContainer instances.
|
||||
if (!(view.parent instanceof ListView)) {
|
||||
this._removeView(view.parent);
|
||||
}
|
||||
view.parent._removeView(view);
|
||||
}
|
||||
});
|
||||
private clearRealizedCells(): void {
|
||||
// clear the cache
|
||||
this._realizedItems.forEach((view, nativeView) => {
|
||||
if (view.parent) {
|
||||
// This is to clear the StackLayout that is used to wrap non LayoutBase & ProxyViewContainer instances.
|
||||
if (!(view.parent instanceof ListView)) {
|
||||
this._removeView(view.parent);
|
||||
}
|
||||
view.parent._removeView(view);
|
||||
}
|
||||
});
|
||||
|
||||
this._realizedItems.clear();
|
||||
this._realizedTemplates.clear();
|
||||
}
|
||||
this._realizedItems.clear();
|
||||
this._realizedTemplates.clear();
|
||||
}
|
||||
|
||||
public isItemAtIndexVisible(index: number): boolean {
|
||||
let nativeView = this.nativeViewProtected;
|
||||
const start = nativeView.getFirstVisiblePosition();
|
||||
const end = nativeView.getLastVisiblePosition();
|
||||
public isItemAtIndexVisible(index: number): boolean {
|
||||
let nativeView = this.nativeViewProtected;
|
||||
const start = nativeView.getFirstVisiblePosition();
|
||||
const end = nativeView.getLastVisiblePosition();
|
||||
|
||||
return (index >= start && index <= end);
|
||||
}
|
||||
return index >= start && index <= end;
|
||||
}
|
||||
|
||||
[separatorColorProperty.getDefault](): { dividerHeight: number, divider: android.graphics.drawable.Drawable } {
|
||||
let nativeView = this.nativeViewProtected;
|
||||
[separatorColorProperty.getDefault](): {
|
||||
dividerHeight: number;
|
||||
divider: android.graphics.drawable.Drawable;
|
||||
} {
|
||||
let nativeView = this.nativeViewProtected;
|
||||
|
||||
return {
|
||||
dividerHeight: nativeView.getDividerHeight(),
|
||||
divider: nativeView.getDivider()
|
||||
};
|
||||
}
|
||||
[separatorColorProperty.setNative](value: Color | { dividerHeight: number, divider: android.graphics.drawable.Drawable }) {
|
||||
let nativeView = this.nativeViewProtected;
|
||||
if (value instanceof Color) {
|
||||
nativeView.setDivider(new android.graphics.drawable.ColorDrawable(value.android));
|
||||
nativeView.setDividerHeight(1);
|
||||
} else {
|
||||
nativeView.setDivider(value.divider);
|
||||
nativeView.setDividerHeight(value.dividerHeight);
|
||||
}
|
||||
}
|
||||
return {
|
||||
dividerHeight: nativeView.getDividerHeight(),
|
||||
divider: nativeView.getDivider(),
|
||||
};
|
||||
}
|
||||
[separatorColorProperty.setNative](
|
||||
value:
|
||||
| Color
|
||||
| {
|
||||
dividerHeight: number;
|
||||
divider: android.graphics.drawable.Drawable;
|
||||
}
|
||||
) {
|
||||
let nativeView = this.nativeViewProtected;
|
||||
if (value instanceof Color) {
|
||||
nativeView.setDivider(
|
||||
new android.graphics.drawable.ColorDrawable(value.android)
|
||||
);
|
||||
nativeView.setDividerHeight(1);
|
||||
} else {
|
||||
nativeView.setDivider(value.divider);
|
||||
nativeView.setDividerHeight(value.dividerHeight);
|
||||
}
|
||||
}
|
||||
|
||||
[itemTemplatesProperty.getDefault](): KeyedTemplate[] {
|
||||
return null;
|
||||
}
|
||||
[itemTemplatesProperty.setNative](value: KeyedTemplate[]) {
|
||||
this._itemTemplatesInternal = new Array<KeyedTemplate>(this._defaultTemplate);
|
||||
if (value) {
|
||||
this._itemTemplatesInternal = this._itemTemplatesInternal.concat(value);
|
||||
}
|
||||
[itemTemplatesProperty.getDefault](): KeyedTemplate[] {
|
||||
return null;
|
||||
}
|
||||
[itemTemplatesProperty.setNative](value: KeyedTemplate[]) {
|
||||
this._itemTemplatesInternal = new Array<KeyedTemplate>(
|
||||
this._defaultTemplate
|
||||
);
|
||||
if (value) {
|
||||
this._itemTemplatesInternal = this._itemTemplatesInternal.concat(
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
|
||||
this.refresh();
|
||||
}
|
||||
this.nativeViewProtected.setAdapter(new ListViewAdapterClass(this));
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
let ListViewAdapterClass;
|
||||
function ensureListViewAdapterClass() {
|
||||
if (ListViewAdapterClass) {
|
||||
return;
|
||||
}
|
||||
if (ListViewAdapterClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
class ListViewAdapter extends android.widget.BaseAdapter {
|
||||
constructor(public owner: ListView) {
|
||||
super();
|
||||
class ListViewAdapter extends android.widget.BaseAdapter {
|
||||
constructor(public owner: ListView) {
|
||||
super();
|
||||
|
||||
return global.__native(this);
|
||||
}
|
||||
return global.__native(this);
|
||||
}
|
||||
|
||||
public getCount() {
|
||||
return this.owner && this.owner.items && this.owner.items.length ? this.owner.items.length : 0;
|
||||
}
|
||||
public getCount() {
|
||||
return this.owner && this.owner.items && this.owner.items.length
|
||||
? this.owner.items.length
|
||||
: 0;
|
||||
}
|
||||
|
||||
public getItem(i: number) {
|
||||
if (this.owner && this.owner.items && i < this.owner.items.length) {
|
||||
let getItem = (<ItemsSource>this.owner.items).getItem;
|
||||
public getItem(i: number) {
|
||||
if (this.owner && this.owner.items && i < this.owner.items.length) {
|
||||
let getItem = (<ItemsSource>this.owner.items).getItem;
|
||||
|
||||
return getItem ? getItem.call(this.owner.items, i) : this.owner.items[i];
|
||||
}
|
||||
return getItem
|
||||
? getItem.call(this.owner.items, i)
|
||||
: this.owner.items[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public getItemId(i: number) {
|
||||
let item = this.getItem(i);
|
||||
let id = i;
|
||||
if (this.owner && item && this.owner.items) {
|
||||
id = this.owner.itemIdGenerator(item, i, this.owner.items);
|
||||
}
|
||||
public getItemId(i: number) {
|
||||
let item = this.getItem(i);
|
||||
let id = i;
|
||||
if (this.owner && item && this.owner.items) {
|
||||
id = this.owner.itemIdGenerator(item, i, this.owner.items);
|
||||
}
|
||||
|
||||
return long(id);
|
||||
}
|
||||
return long(id);
|
||||
}
|
||||
|
||||
public hasStableIds(): boolean {
|
||||
return true;
|
||||
}
|
||||
public hasStableIds(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
public getViewTypeCount() {
|
||||
return this.owner._itemTemplatesInternal.length;
|
||||
}
|
||||
public getViewTypeCount() {
|
||||
return this.owner._itemTemplatesInternal.length;
|
||||
}
|
||||
|
||||
public getItemViewType(index: number) {
|
||||
let template = this.owner._getItemTemplate(index);
|
||||
let itemViewType = this.owner._itemTemplatesInternal.indexOf(template);
|
||||
public getItemViewType(index: number) {
|
||||
let template = this.owner._getItemTemplate(index);
|
||||
let itemViewType = this.owner._itemTemplatesInternal.indexOf(
|
||||
template
|
||||
);
|
||||
|
||||
return itemViewType;
|
||||
}
|
||||
return itemViewType;
|
||||
}
|
||||
|
||||
@profile()
|
||||
public getView(index: number, convertView: android.view.View, parent: android.view.ViewGroup): android.view.View {
|
||||
//this.owner._dumpRealizedTemplates();
|
||||
@profile()
|
||||
public getView(
|
||||
index: number,
|
||||
convertView: android.view.View,
|
||||
parent: android.view.ViewGroup
|
||||
): android.view.View {
|
||||
//this.owner._dumpRealizedTemplates();
|
||||
|
||||
if (!this.owner) {
|
||||
return null;
|
||||
}
|
||||
if (!this.owner) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let totalItemCount = this.owner.items ? this.owner.items.length : 0;
|
||||
if (index === (totalItemCount - 1)) {
|
||||
this.owner.notify({ eventName: LOADMOREITEMS, object: this.owner });
|
||||
}
|
||||
let totalItemCount = this.owner.items ? this.owner.items.length : 0;
|
||||
if (index === totalItemCount - 1) {
|
||||
this.owner.notify({
|
||||
eventName: LOADMOREITEMS,
|
||||
object: this.owner,
|
||||
});
|
||||
}
|
||||
|
||||
// Recycle an existing view or create a new one if needed.
|
||||
let template = this.owner._getItemTemplate(index);
|
||||
let view: View;
|
||||
if (convertView) {
|
||||
view = this.owner._realizedTemplates.get(template.key).get(convertView);
|
||||
if (!view) {
|
||||
throw new Error(`There is no entry with key '${convertView}' in the realized views cache for template with key'${template.key}'.`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
view = template.createView();
|
||||
}
|
||||
// Recycle an existing view or create a new one if needed.
|
||||
let template = this.owner._getItemTemplate(index);
|
||||
let view: View;
|
||||
if (convertView) {
|
||||
view = this.owner._realizedTemplates
|
||||
.get(template.key)
|
||||
.get(convertView);
|
||||
if (!view) {
|
||||
throw new Error(
|
||||
`There is no entry with key '${convertView}' in the realized views cache for template with key'${template.key}'.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
view = template.createView();
|
||||
}
|
||||
|
||||
let args: ItemEventData = {
|
||||
eventName: ITEMLOADING, object: this.owner, index: index, view: view,
|
||||
android: parent,
|
||||
ios: undefined
|
||||
};
|
||||
let args: ItemEventData = {
|
||||
eventName: ITEMLOADING,
|
||||
object: this.owner,
|
||||
index: index,
|
||||
view: view,
|
||||
android: parent,
|
||||
ios: undefined,
|
||||
};
|
||||
|
||||
this.owner.notify(args);
|
||||
this.owner.notify(args);
|
||||
|
||||
if (!args.view) {
|
||||
args.view = this.owner._getDefaultItemContent(index);
|
||||
}
|
||||
if (!args.view) {
|
||||
args.view = this.owner._getDefaultItemContent(index);
|
||||
}
|
||||
|
||||
if (args.view) {
|
||||
if (this.owner._effectiveRowHeight > -1) {
|
||||
args.view.height = this.owner.rowHeight;
|
||||
}
|
||||
else {
|
||||
args.view.height = <Length>unsetValue;
|
||||
}
|
||||
if (args.view) {
|
||||
if (this.owner._effectiveRowHeight > -1) {
|
||||
args.view.height = this.owner.rowHeight;
|
||||
} else {
|
||||
args.view.height = <Length>unsetValue;
|
||||
}
|
||||
|
||||
this.owner._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 &&
|
||||
!(args.view instanceof ProxyViewContainer)) {
|
||||
this.owner._addView(args.view);
|
||||
convertView = args.view.nativeViewProtected;
|
||||
} else {
|
||||
let sp = new StackLayout();
|
||||
sp.addChild(args.view);
|
||||
this.owner._addView(sp);
|
||||
this.owner._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 &&
|
||||
!(args.view instanceof ProxyViewContainer)
|
||||
) {
|
||||
this.owner._addView(args.view);
|
||||
convertView = args.view.nativeViewProtected;
|
||||
} else {
|
||||
let sp = new StackLayout();
|
||||
sp.addChild(args.view);
|
||||
this.owner._addView(sp);
|
||||
|
||||
convertView = sp.nativeViewProtected;
|
||||
}
|
||||
}
|
||||
convertView = sp.nativeViewProtected;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the view for recycling
|
||||
let realizedItemsForTemplateKey = this.owner._realizedTemplates.get(template.key);
|
||||
if (!realizedItemsForTemplateKey) {
|
||||
realizedItemsForTemplateKey = new Map<android.view.View, View>();
|
||||
this.owner._realizedTemplates.set(template.key, realizedItemsForTemplateKey);
|
||||
}
|
||||
realizedItemsForTemplateKey.set(convertView, args.view);
|
||||
this.owner._realizedItems.set(convertView, args.view);
|
||||
}
|
||||
// Cache the view for recycling
|
||||
let realizedItemsForTemplateKey = this.owner._realizedTemplates.get(
|
||||
template.key
|
||||
);
|
||||
if (!realizedItemsForTemplateKey) {
|
||||
realizedItemsForTemplateKey = new Map<
|
||||
android.view.View,
|
||||
View
|
||||
>();
|
||||
this.owner._realizedTemplates.set(
|
||||
template.key,
|
||||
realizedItemsForTemplateKey
|
||||
);
|
||||
}
|
||||
realizedItemsForTemplateKey.set(convertView, args.view);
|
||||
this.owner._realizedItems.set(convertView, args.view);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
ListViewAdapterClass = ListViewAdapter;
|
||||
ListViewAdapterClass = ListViewAdapter;
|
||||
}
|
||||
|
||||
289
nativescript-core/ui/list-view/index.d.ts
vendored
289
nativescript-core/ui/list-view/index.d.ts
vendored
@@ -1,180 +1,202 @@
|
||||
import { View, Template, KeyedTemplate } from "../core/view";
|
||||
import { Color } from '../../color';
|
||||
import { EventData } from '../../data/observable';
|
||||
import { Length } from '../styling/style-properties';
|
||||
import { Style } from '../styling/style';
|
||||
import { Color } from "../../color";
|
||||
import { EventData } from "../../data/observable";
|
||||
import { Length } from "../styling/style-properties";
|
||||
import { Style } from "../styling/style";
|
||||
import { Property, CssProperty } from "../core/properties";
|
||||
|
||||
/**
|
||||
* Known template names.
|
||||
*/
|
||||
export module knownTemplates {
|
||||
/**
|
||||
* The ListView item template.
|
||||
*/
|
||||
export const itemTemplate: string;
|
||||
/**
|
||||
* The ListView item template.
|
||||
*/
|
||||
export const itemTemplate: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a view that shows items in a vertically scrolling list.
|
||||
*/
|
||||
export class ListView extends View {
|
||||
/**
|
||||
* String value used when hooking to itemLoading event.
|
||||
*/
|
||||
public static itemLoadingEvent: string;
|
||||
/**
|
||||
* String value used when hooking to itemTap event.
|
||||
*/
|
||||
public static itemTapEvent: string;
|
||||
/**
|
||||
* String value used when hooking to loadMoreItems event.
|
||||
*/
|
||||
public static loadMoreItemsEvent: string;
|
||||
/**
|
||||
* String value used when hooking to itemLoading event.
|
||||
*/
|
||||
public static itemLoadingEvent: string;
|
||||
/**
|
||||
* String value used when hooking to itemTap event.
|
||||
*/
|
||||
public static itemTapEvent: string;
|
||||
/**
|
||||
* String value used when hooking to loadMoreItems event.
|
||||
*/
|
||||
public static loadMoreItemsEvent: string;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
android: any /* android.widget.ListView */;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
android: any /* android.widget.ListView */;
|
||||
|
||||
/**
|
||||
* Gets the native [iOS view](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/) that represents the user interface for this component. Valid only when running on iOS.
|
||||
*/
|
||||
ios: any /* UITableView */;
|
||||
/**
|
||||
* Gets the native [iOS view](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/) that represents the user interface for this component. Valid only when running on iOS.
|
||||
*/
|
||||
ios: any /* UITableView */;
|
||||
|
||||
/**
|
||||
* 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[] | ItemsSource;
|
||||
/**
|
||||
* 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[] | ItemsSource;
|
||||
|
||||
/**
|
||||
* Gets or set the item template of the ListView.
|
||||
*/
|
||||
itemTemplate: string | Template;
|
||||
/**
|
||||
* Gets or set the item template of the ListView.
|
||||
*/
|
||||
itemTemplate: string | Template;
|
||||
|
||||
/**
|
||||
* Gets or set the list of item templates for the item template selector
|
||||
*/
|
||||
itemTemplates: string | Array<KeyedTemplate>;
|
||||
/**
|
||||
* Gets or set the list of item templates for the item template selector
|
||||
*/
|
||||
itemTemplates: string | Array<KeyedTemplate>;
|
||||
|
||||
/**
|
||||
* A function that returns the appropriate ket template based on the data item.
|
||||
*/
|
||||
itemTemplateSelector: string | ((item: any, index: number, items: any) => string);
|
||||
/**
|
||||
* A function that returns the appropriate ket template based on the data item.
|
||||
*/
|
||||
itemTemplateSelector:
|
||||
| string
|
||||
| ((item: any, index: number, items: any) => string);
|
||||
|
||||
/**
|
||||
* Item id generator
|
||||
*/
|
||||
itemIdGenerator: (item: any, index: number, items: any) => number;
|
||||
/**
|
||||
* Item id generator
|
||||
*/
|
||||
itemIdGenerator: (item: any, index: number, items: any) => number;
|
||||
|
||||
/**
|
||||
* Gets or set the items separator line color of the ListView.
|
||||
*/
|
||||
separatorColor: Color;
|
||||
/**
|
||||
* Gets or set the items separator line color of the ListView.
|
||||
*/
|
||||
separatorColor: Color;
|
||||
|
||||
/**
|
||||
* Gets or set row height of the ListView.
|
||||
*/
|
||||
rowHeight: Length;
|
||||
/**
|
||||
* Gets or set row height of the ListView.
|
||||
*/
|
||||
rowHeight: Length;
|
||||
|
||||
/**
|
||||
* Gets or set the estimated height of rows in the ListView.
|
||||
* The default value is 44px.
|
||||
*/
|
||||
iosEstimatedRowHeight: Length;
|
||||
/**
|
||||
* Gets or set the estimated height of rows in the ListView.
|
||||
* The default value is 44px.
|
||||
*/
|
||||
iosEstimatedRowHeight: Length;
|
||||
|
||||
/**
|
||||
* Forces the ListView to reload all its items.
|
||||
*/
|
||||
refresh();
|
||||
/**
|
||||
* Forces the ListView to reload all its items.
|
||||
*/
|
||||
refresh();
|
||||
|
||||
/**
|
||||
* Scrolls the specified item with index into view.
|
||||
* [iOS](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instm/UITableView/scrollToRowAtIndexPath:atScrollPosition:animated:)
|
||||
* [Android](http://developer.android.com/reference/android/widget/ListView.html#setSelection(int))
|
||||
* @param index - Item index.
|
||||
*/
|
||||
scrollToIndex(index: number);
|
||||
/**
|
||||
* Scrolls the specified item with index into view.
|
||||
* [iOS](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instm/UITableView/scrollToRowAtIndexPath:atScrollPosition:animated:)
|
||||
* [Android](http://developer.android.com/reference/android/widget/ListView.html#setSelection(int))
|
||||
* @param index - Item index.
|
||||
*/
|
||||
scrollToIndex(index: number);
|
||||
|
||||
/**
|
||||
* Scrolls the specified item with index into view with animation.
|
||||
* [iOS](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instm/UITableView/scrollToRowAtIndexPath:atScrollPosition:animated:)
|
||||
* [Android](https://developer.android.com/reference/android/widget/ListView.html#smoothScrollToPosition(int))
|
||||
* @param index - Item index.
|
||||
*/
|
||||
scrollToIndexAnimated(index: number);
|
||||
/**
|
||||
* Scrolls the specified item with index into view with animation.
|
||||
* [iOS](https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instm/UITableView/scrollToRowAtIndexPath:atScrollPosition:animated:)
|
||||
* [Android](https://developer.android.com/reference/android/widget/ListView.html#smoothScrollToPosition(int))
|
||||
* @param index - Item index.
|
||||
*/
|
||||
scrollToIndexAnimated(index: number);
|
||||
|
||||
/**
|
||||
* Checks if Specified item with index is visible.
|
||||
* @param index - Item index.
|
||||
*/
|
||||
isItemAtIndexVisible(index: number): boolean;
|
||||
/**
|
||||
* Checks if Specified item with index is visible.
|
||||
* @param index - Item index.
|
||||
*/
|
||||
isItemAtIndexVisible(index: number): boolean;
|
||||
|
||||
/**
|
||||
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
|
||||
* @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change").
|
||||
* @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: EventData) => void, thisArg?: any);
|
||||
/**
|
||||
* A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
|
||||
* @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change").
|
||||
* @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: EventData) => void, thisArg?: any);
|
||||
|
||||
/**
|
||||
* Raised when a View for the data at the specified index should be created.
|
||||
* The result should be returned trough the view property of the event data.
|
||||
* Note, that the view property of the event data can be pre-initialized with
|
||||
* an old instance of a view, so that it can be reused.
|
||||
*/
|
||||
on(event: "itemLoading", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
/**
|
||||
* Raised when a View for the data at the specified index should be created.
|
||||
* The result should be returned trough the view property of the event data.
|
||||
* Note, that the view property of the event data can be pre-initialized with
|
||||
* an old instance of a view, so that it can be reused.
|
||||
*/
|
||||
on(
|
||||
event: "itemLoading",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
|
||||
/**
|
||||
* Raised when an item inside the ListView is tapped.
|
||||
*/
|
||||
on(event: "itemTap", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
/**
|
||||
* Raised when an item inside the ListView is tapped.
|
||||
*/
|
||||
on(
|
||||
event: "itemTap",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
|
||||
/**
|
||||
* Raised when the ListView is scrolled so that its last item is visible.
|
||||
*/
|
||||
on(event: "loadMoreItems", callback: (args: EventData) => void, thisArg?: any);
|
||||
/**
|
||||
* Raised when the ListView is scrolled so that its last item is visible.
|
||||
*/
|
||||
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 EventData {
|
||||
/**
|
||||
* The index of the item, for which the event is raised.
|
||||
*/
|
||||
index: number;
|
||||
/**
|
||||
* The index of the item, for which the event is raised.
|
||||
*/
|
||||
index: number;
|
||||
|
||||
/**
|
||||
* The view that is associated to the item, for which the event is raised.
|
||||
*/
|
||||
view: View;
|
||||
/**
|
||||
* The view that is associated to the item, for which the event is raised.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
ios: any /* UITableViewCell */;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
ios: any /* UITableViewCell */;
|
||||
|
||||
/**
|
||||
* Gets the native [android widget](http://developer.android.com/reference/android/view/ViewGroup.html) that represents the user interface where the view is hosted. Valid only when running on Android OS.
|
||||
*/
|
||||
android: any /* android.view.ViewGroup */;
|
||||
/**
|
||||
* Gets the native [android widget](http://developer.android.com/reference/android/view/ViewGroup.html) that represents the user interface where the view is hosted. Valid only when running on Android OS.
|
||||
*/
|
||||
android: any /* android.view.ViewGroup */;
|
||||
}
|
||||
|
||||
export interface ItemsSource {
|
||||
length: number;
|
||||
getItem(index: number): any;
|
||||
length: number;
|
||||
getItem(index: number): any;
|
||||
}
|
||||
|
||||
export interface TemplatedItemsView {
|
||||
items: any[] | ItemsSource;
|
||||
itemTemplate: string | Template;
|
||||
itemTemplates?: string | Array<KeyedTemplate>;
|
||||
refresh(): void;
|
||||
on(event: "itemLoading", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
off(event: "itemLoading", callback: (args: EventData) => void, thisArg?: any);
|
||||
items: any[] | ItemsSource;
|
||||
itemTemplate: string | Template;
|
||||
itemTemplates?: string | Array<KeyedTemplate>;
|
||||
refresh(): void;
|
||||
on(
|
||||
event: "itemLoading",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
off(
|
||||
event: "itemLoading",
|
||||
callback: (args: EventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,7 +212,10 @@ export const itemTemplateProperty: Property<ListView, string | Template>;
|
||||
/**
|
||||
* Represents the items template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplatesProperty: Property<ListView, string | Array<KeyedTemplate>>;
|
||||
export const itemTemplatesProperty: Property<
|
||||
ListView,
|
||||
string | Array<KeyedTemplate>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Represents the separator color backing property.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,16 @@
|
||||
import { ListView as ListViewDefinition, ItemsSource, ItemEventData, TemplatedItemsView } from ".";
|
||||
import { View, ContainerView, Template, KeyedTemplate, CSSType } from "../core/view";
|
||||
import {
|
||||
ListView as ListViewDefinition,
|
||||
ItemsSource,
|
||||
ItemEventData,
|
||||
TemplatedItemsView,
|
||||
} from ".";
|
||||
import {
|
||||
View,
|
||||
ContainerView,
|
||||
Template,
|
||||
KeyedTemplate,
|
||||
CSSType,
|
||||
} from "../core/view";
|
||||
import { Property, CoercibleProperty, CssProperty } from "../core/properties";
|
||||
import { Length } from "../styling/style-properties";
|
||||
import { Style } from "../styling/style";
|
||||
@@ -8,205 +19,269 @@ import { Builder } from "../builder";
|
||||
import { Label } from "../label";
|
||||
import { Observable, EventData } from "../../data/observable";
|
||||
import { ObservableArray, ChangedData } from "../../data/observable-array";
|
||||
import { addWeakEventListener, removeWeakEventListener } from "../core/weak-event-listener";
|
||||
import {
|
||||
addWeakEventListener,
|
||||
removeWeakEventListener,
|
||||
} from "../core/weak-event-listener";
|
||||
|
||||
// TODO: Think of a way to register these instead of relying on hardcoded values.
|
||||
export module knownTemplates {
|
||||
export const itemTemplate = "itemTemplate";
|
||||
export const itemTemplate = "itemTemplate";
|
||||
}
|
||||
|
||||
export module knownMultiTemplates {
|
||||
export const itemTemplates = "itemTemplates";
|
||||
export const itemTemplates = "itemTemplates";
|
||||
}
|
||||
|
||||
const autoEffectiveRowHeight = -1;
|
||||
|
||||
@CSSType("ListView")
|
||||
export abstract class ListViewBase extends ContainerView implements ListViewDefinition, TemplatedItemsView {
|
||||
public static itemLoadingEvent = "itemLoading";
|
||||
public static itemTapEvent = "itemTap";
|
||||
public static loadMoreItemsEvent = "loadMoreItems";
|
||||
// TODO: get rid of such hacks.
|
||||
public static knownFunctions = ["itemTemplateSelector", "itemIdGenerator"]; //See component-builder.ts isKnownFunction
|
||||
export abstract class ListViewBase extends ContainerView
|
||||
implements ListViewDefinition, TemplatedItemsView {
|
||||
public static itemLoadingEvent = "itemLoading";
|
||||
public static itemTapEvent = "itemTap";
|
||||
public static loadMoreItemsEvent = "loadMoreItems";
|
||||
// TODO: get rid of such hacks.
|
||||
public static knownFunctions = ["itemTemplateSelector", "itemIdGenerator"]; //See component-builder.ts isKnownFunction
|
||||
|
||||
private _itemIdGenerator: (item: any, index: number, items: any) => number = (_item: any, index: number) => index;
|
||||
private _itemTemplateSelector: (item: any, index: number, items: any) => string;
|
||||
private _itemTemplateSelectorBindable = new Label();
|
||||
public _defaultTemplate: KeyedTemplate = {
|
||||
key: "default",
|
||||
createView: () => {
|
||||
if (this.itemTemplate) {
|
||||
return Builder.parse(this.itemTemplate, this);
|
||||
}
|
||||
private _itemIdGenerator: (
|
||||
item: any,
|
||||
index: number,
|
||||
items: any
|
||||
) => number = (_item: any, index: number) => index;
|
||||
private _itemTemplateSelector: (
|
||||
item: any,
|
||||
index: number,
|
||||
items: any
|
||||
) => string;
|
||||
private _itemTemplateSelectorBindable = new Label();
|
||||
public _defaultTemplate: KeyedTemplate = {
|
||||
key: "default",
|
||||
createView: () => {
|
||||
if (this.itemTemplate) {
|
||||
return Builder.parse(this.itemTemplate, this);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
public _itemTemplatesInternal = new Array<KeyedTemplate>(this._defaultTemplate);
|
||||
public _effectiveRowHeight: number = autoEffectiveRowHeight;
|
||||
public rowHeight: Length;
|
||||
public iosEstimatedRowHeight: Length;
|
||||
public items: any[] | ItemsSource;
|
||||
public itemTemplate: string | Template;
|
||||
public itemTemplates: string | Array<KeyedTemplate>;
|
||||
public _itemTemplatesInternal = new Array<KeyedTemplate>(
|
||||
this._defaultTemplate
|
||||
);
|
||||
public _effectiveRowHeight: number = autoEffectiveRowHeight;
|
||||
public rowHeight: Length;
|
||||
public iosEstimatedRowHeight: Length;
|
||||
public items: any[] | ItemsSource;
|
||||
public itemTemplate: string | Template;
|
||||
public itemTemplates: string | Array<KeyedTemplate>;
|
||||
|
||||
get separatorColor(): Color {
|
||||
return this.style.separatorColor;
|
||||
}
|
||||
set separatorColor(value: Color) {
|
||||
this.style.separatorColor = value;
|
||||
}
|
||||
get separatorColor(): Color {
|
||||
return this.style.separatorColor;
|
||||
}
|
||||
set separatorColor(value: Color) {
|
||||
this.style.separatorColor = value;
|
||||
}
|
||||
|
||||
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 (typeof value === "string") {
|
||||
this._itemTemplateSelectorBindable.bind({
|
||||
sourceProperty: null,
|
||||
targetProperty: "templateKey",
|
||||
expression: value
|
||||
});
|
||||
this._itemTemplateSelector = (item: any, index: number, items: any) => {
|
||||
item["$index"] = index;
|
||||
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 (typeof value === "string") {
|
||||
this._itemTemplateSelectorBindable.bind({
|
||||
sourceProperty: null,
|
||||
targetProperty: "templateKey",
|
||||
expression: value,
|
||||
});
|
||||
this._itemTemplateSelector = (
|
||||
item: any,
|
||||
index: number,
|
||||
items: any
|
||||
) => {
|
||||
item["$index"] = index;
|
||||
|
||||
if (this._itemTemplateSelectorBindable.bindingContext === item) {
|
||||
this._itemTemplateSelectorBindable.bindingContext = null;
|
||||
}
|
||||
if (
|
||||
this._itemTemplateSelectorBindable.bindingContext === item
|
||||
) {
|
||||
this._itemTemplateSelectorBindable.bindingContext = null;
|
||||
}
|
||||
|
||||
this._itemTemplateSelectorBindable.bindingContext = item;
|
||||
this._itemTemplateSelectorBindable.bindingContext = item;
|
||||
|
||||
return this._itemTemplateSelectorBindable.get("templateKey");
|
||||
};
|
||||
}
|
||||
else if (typeof value === "function") {
|
||||
this._itemTemplateSelector = value;
|
||||
}
|
||||
}
|
||||
return this._itemTemplateSelectorBindable.get("templateKey");
|
||||
};
|
||||
} else if (typeof value === "function") {
|
||||
this._itemTemplateSelector = value;
|
||||
}
|
||||
}
|
||||
|
||||
get itemIdGenerator(): (item: any, index: number, items: any) => number {
|
||||
return this._itemIdGenerator;
|
||||
}
|
||||
set itemIdGenerator(generatorFn: (item: any, index: number, items: any) => number) {
|
||||
this._itemIdGenerator = generatorFn;
|
||||
}
|
||||
get itemIdGenerator(): (item: any, index: number, items: any) => number {
|
||||
return this._itemIdGenerator;
|
||||
}
|
||||
set itemIdGenerator(
|
||||
generatorFn: (item: any, index: number, items: any) => number
|
||||
) {
|
||||
this._itemIdGenerator = generatorFn;
|
||||
}
|
||||
|
||||
public refresh() {
|
||||
//
|
||||
}
|
||||
public refresh() {
|
||||
//
|
||||
}
|
||||
|
||||
public scrollToIndex(index: number) {
|
||||
//
|
||||
}
|
||||
public scrollToIndex(index: number) {
|
||||
//
|
||||
}
|
||||
|
||||
public scrollToIndexAnimated(index: number) {
|
||||
//
|
||||
}
|
||||
public scrollToIndexAnimated(index: number) {
|
||||
//
|
||||
}
|
||||
|
||||
public _getItemTemplate(index: number): KeyedTemplate {
|
||||
let templateKey = "default";
|
||||
if (this.itemTemplateSelector) {
|
||||
let dataItem = this._getDataItem(index);
|
||||
templateKey = this._itemTemplateSelector(dataItem, index, this.items);
|
||||
}
|
||||
public _getItemTemplate(index: number): KeyedTemplate {
|
||||
let templateKey = "default";
|
||||
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) {
|
||||
return this._itemTemplatesInternal[i];
|
||||
}
|
||||
}
|
||||
for (
|
||||
let i = 0, length = this._itemTemplatesInternal.length;
|
||||
i < length;
|
||||
i++
|
||||
) {
|
||||
if (this._itemTemplatesInternal[i].key === templateKey) {
|
||||
return this._itemTemplatesInternal[i];
|
||||
}
|
||||
}
|
||||
|
||||
// This is the default template
|
||||
return this._itemTemplatesInternal[0];
|
||||
}
|
||||
// This is the default template
|
||||
return this._itemTemplatesInternal[0];
|
||||
}
|
||||
|
||||
public _prepareItem(item: View, index: number) {
|
||||
if (item) {
|
||||
item.bindingContext = this._getDataItem(index);
|
||||
}
|
||||
}
|
||||
public _prepareItem(item: View, index: number) {
|
||||
if (item) {
|
||||
item.bindingContext = this._getDataItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
private _getDataItem(index: number): any {
|
||||
let thisItems = <ItemsSource>this.items;
|
||||
private _getDataItem(index: number): any {
|
||||
let thisItems = <ItemsSource>this.items;
|
||||
|
||||
return thisItems.getItem ? thisItems.getItem(index) : thisItems[index];
|
||||
}
|
||||
return thisItems.getItem ? thisItems.getItem(index) : thisItems[index];
|
||||
}
|
||||
|
||||
public _getDefaultItemContent(index: number): View {
|
||||
let lbl = new Label();
|
||||
lbl.bind({
|
||||
targetProperty: "text",
|
||||
sourceProperty: "$value"
|
||||
});
|
||||
public _getDefaultItemContent(index: number): View {
|
||||
let lbl = new Label();
|
||||
lbl.bind({
|
||||
targetProperty: "text",
|
||||
sourceProperty: "$value",
|
||||
});
|
||||
|
||||
return lbl;
|
||||
}
|
||||
return lbl;
|
||||
}
|
||||
|
||||
public _onItemsChanged(args: ChangedData<any>) {
|
||||
this.refresh();
|
||||
}
|
||||
public _onItemsChanged(args: ChangedData<any>) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
public _onRowHeightPropertyChanged(oldValue: Length, newValue: Length) {
|
||||
this.refresh();
|
||||
}
|
||||
public _onRowHeightPropertyChanged(oldValue: Length, newValue: Length) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
public isItemAtIndexVisible(index: number) {
|
||||
return false;
|
||||
}
|
||||
public isItemAtIndexVisible(index: number) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected updateEffectiveRowHeight(): void {
|
||||
rowHeightProperty.coerce(this);
|
||||
}
|
||||
protected updateEffectiveRowHeight(): void {
|
||||
rowHeightProperty.coerce(this);
|
||||
}
|
||||
}
|
||||
ListViewBase.prototype.recycleNativeView = "auto";
|
||||
|
||||
export interface ListViewBase {
|
||||
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
|
||||
on(event: "itemLoading", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
on(event: "itemTap", callback: (args: ItemEventData) => void, thisArg?: any);
|
||||
on(event: "loadMoreItems", callback: (args: EventData) => void, thisArg?: any);
|
||||
on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
|
||||
on(
|
||||
event: "itemLoading",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
on(
|
||||
event: "itemTap",
|
||||
callback: (args: ItemEventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
on(
|
||||
event: "loadMoreItems",
|
||||
callback: (args: EventData) => void,
|
||||
thisArg?: any
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
name: "items",
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
if (oldValue instanceof Observable) {
|
||||
removeWeakEventListener(
|
||||
oldValue,
|
||||
ObservableArray.changeEvent,
|
||||
target._onItemsChanged,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
if (newValue instanceof Observable) {
|
||||
addWeakEventListener(newValue, ObservableArray.changeEvent, target._onItemsChanged, target);
|
||||
}
|
||||
if (newValue instanceof Observable) {
|
||||
addWeakEventListener(
|
||||
newValue,
|
||||
ObservableArray.changeEvent,
|
||||
target._onItemsChanged,
|
||||
target
|
||||
);
|
||||
}
|
||||
|
||||
target.refresh();
|
||||
}
|
||||
target.refresh();
|
||||
},
|
||||
});
|
||||
itemsProperty.register(ListViewBase);
|
||||
|
||||
/**
|
||||
* Represents the item template property of each ListView instance.
|
||||
*/
|
||||
export const itemTemplateProperty = new Property<ListViewBase, string | Template>({
|
||||
name: "itemTemplate", valueChanged: (target) => {
|
||||
target.refresh();
|
||||
}
|
||||
export const itemTemplateProperty = new Property<
|
||||
ListViewBase,
|
||||
string | Template
|
||||
>({
|
||||
name: "itemTemplate",
|
||||
valueChanged: (target) => {
|
||||
target.refresh();
|
||||
},
|
||||
});
|
||||
itemTemplateProperty.register(ListViewBase);
|
||||
|
||||
/**
|
||||
* 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 Builder.parseMultipleTemplates(value, null);
|
||||
}
|
||||
export const itemTemplatesProperty = new Property<
|
||||
ListViewBase,
|
||||
string | Array<KeyedTemplate>
|
||||
>({
|
||||
name: "itemTemplates",
|
||||
valueConverter: (value) => {
|
||||
if (typeof value === "string") {
|
||||
return Builder.parseMultipleTemplates(value, null);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
});
|
||||
itemTemplatesProperty.register(ListViewBase);
|
||||
|
||||
@@ -215,22 +290,36 @@ const defaultRowHeight: Length = "auto";
|
||||
* Represents the observable property backing the rowHeight property of each ListView instance.
|
||||
*/
|
||||
export const rowHeightProperty = new CoercibleProperty<ListViewBase, Length>({
|
||||
name: "rowHeight", defaultValue: defaultRowHeight, equalityComparer: Length.equals,
|
||||
coerceValue: (target, value) => {
|
||||
// We coerce to default value if we don't have display density.
|
||||
return target.nativeViewProtected ? value : defaultRowHeight;
|
||||
},
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
target._effectiveRowHeight = Length.toDevicePixels(newValue, autoEffectiveRowHeight);
|
||||
target._onRowHeightPropertyChanged(oldValue, newValue);
|
||||
}, valueConverter: Length.parse
|
||||
name: "rowHeight",
|
||||
defaultValue: defaultRowHeight,
|
||||
equalityComparer: Length.equals,
|
||||
coerceValue: (target, value) => {
|
||||
// We coerce to default value if we don't have display density.
|
||||
return target.nativeViewProtected ? value : defaultRowHeight;
|
||||
},
|
||||
valueChanged: (target, oldValue, newValue) => {
|
||||
target._effectiveRowHeight = Length.toDevicePixels(
|
||||
newValue,
|
||||
autoEffectiveRowHeight
|
||||
);
|
||||
target._onRowHeightPropertyChanged(oldValue, newValue);
|
||||
},
|
||||
valueConverter: Length.parse,
|
||||
});
|
||||
rowHeightProperty.register(ListViewBase);
|
||||
|
||||
export const iosEstimatedRowHeightProperty = new Property<ListViewBase, Length>({
|
||||
name: "iosEstimatedRowHeight", valueConverter: (v) => Length.parse(v)
|
||||
});
|
||||
export const iosEstimatedRowHeightProperty = new Property<ListViewBase, Length>(
|
||||
{
|
||||
name: "iosEstimatedRowHeight",
|
||||
valueConverter: (v) => Length.parse(v),
|
||||
}
|
||||
);
|
||||
iosEstimatedRowHeightProperty.register(ListViewBase);
|
||||
|
||||
export const separatorColorProperty = new CssProperty<Style, Color>({ name: "separatorColor", cssName: "separator-color", equalityComparer: Color.equals, valueConverter: (v) => new Color(v) });
|
||||
export const separatorColorProperty = new CssProperty<Style, Color>({
|
||||
name: "separatorColor",
|
||||
cssName: "separator-color",
|
||||
equalityComparer: Color.equals,
|
||||
valueConverter: (v) => new Color(v),
|
||||
});
|
||||
separatorColorProperty.register(Style);
|
||||
|
||||
Reference in New Issue
Block a user