diff --git a/ui/list-view/list-view-common.ts b/ui/list-view/list-view-common.ts index 46b72f07d..4ec9876fb 100644 --- a/ui/list-view/list-view-common.ts +++ b/ui/list-view/list-view-common.ts @@ -14,6 +14,7 @@ var ITEMTEMPLATE = "itemTemplate"; var ISSCROLLING = "isScrolling"; var LISTVIEW = "ListView"; var SEPARATORCOLOR = "separatorColor"; +var ROWHEIGHT = "rowHeight"; export module knownTemplates { export var itemTemplate = "itemTemplate"; @@ -29,6 +30,11 @@ function onItemTemplatePropertyChanged(data: dependencyObservable.PropertyChange listView.refresh(); } +function onRowHeightPropertyChanged(data: dependencyObservable.PropertyChangeData) { + var listView = data.object; + listView._onRowHeightPropertyChanged(data); +} + export class ListView extends view.View implements definition.ListView { public static itemLoadingEvent = "itemLoading"; public static itemTapEvent = "itemTap"; @@ -66,7 +72,17 @@ export class ListView extends view.View implements definition.ListView { 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); @@ -97,6 +113,13 @@ export class ListView extends view.View implements definition.ListView { value instanceof color.Color ? value : new color.Color(value)); } + get rowHeight(): number { + return this._getValue(ListView.rowHeightProperty); + } + set rowHeight(value: number) { + this._setValue(ListView.rowHeightProperty, value); + } + public refresh() { // } @@ -155,6 +178,10 @@ export class ListView extends view.View implements definition.ListView { this.refresh(); } + public _onRowHeightPropertyChanged(data: dependencyObservable.PropertyChangeData) { + this.refresh(); + } + public _propagateInheritableProperties(view: view.View) { // do not get binding context from parent when adding items, since the binding context of the items will be different. } diff --git a/ui/list-view/list-view.android.ts b/ui/list-view/list-view.android.ts index 131754dc2..3de50b6d7 100644 --- a/ui/list-view/list-view.android.ts +++ b/ui/list-view/list-view.android.ts @@ -205,6 +205,12 @@ class ListViewAdapter extends android.widget.BaseAdapter { } if (args.view) { + if (this._listView.rowHeight > -1) { + args.view.height = this._listView.rowHeight; + } + else { + args.view.height = Number.NaN; + } this._listView._prepareItem(args.view, index); if (!args.view.parent) { if (args.view instanceof layoutBaseModule.LayoutBase) { diff --git a/ui/list-view/list-view.d.ts b/ui/list-view/list-view.d.ts index 798fbae82..5901fadbb 100644 --- a/ui/list-view/list-view.d.ts +++ b/ui/list-view/list-view.d.ts @@ -49,6 +49,11 @@ declare module "ui/list-view" { */ 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. */ @@ -80,6 +85,11 @@ declare module "ui/list-view" { */ separatorColor: color.Color; + /** + * Gets or set row height of the ListView. + */ + rowHeight: number; + /** * Forces the ListView to reload all its items. */ diff --git a/ui/list-view/list-view.ios.ts b/ui/list-view/list-view.ios.ts index 35ca5db0c..968c285ca 100644 --- a/ui/list-view/list-view.ios.ts +++ b/ui/list-view/list-view.ios.ts @@ -11,7 +11,7 @@ var CELLIDENTIFIER = "cell"; var ITEMLOADING = common.ListView.itemLoadingEvent; var LOADMOREITEMS = common.ListView.loadMoreItemsEvent; var ITEMTAP = common.ListView.itemTapEvent; -var DEFAULT_HEIGHT = 80; +var DEFAULT_HEIGHT = 44; global.moduleMerge(common, exports); @@ -69,7 +69,8 @@ class DataSource extends NSObject implements UITableViewDataSource { // Arrange cell views. We do it here instead of _layoutCell because _layoutCell is called // from 'tableViewHeightForRowAtIndexPath' method too (in iOS 7.1) and we don't want to arrange the fake cell. let width = utils.layout.getMeasureSpecSize(owner.widthMeasureSpec); - let cellHeight = owner.getHeight(indexPath.row); + let rowHeight = owner._nativeView.rowHeight; + let cellHeight = rowHeight > 0 ? rowHeight : owner.getHeight(indexPath.row); view.View.layoutChild(owner, cellView, 0, 0, width, cellHeight); } } @@ -132,6 +133,35 @@ class UITableViewDelegateImpl extends NSObject implements UITableViewDelegate { } } +class UITableViewRowHeightDelegateImpl extends NSObject implements UITableViewDelegate { + public static ObjCProtocols = [UITableViewDelegate]; + + private _owner: WeakRef; + + public static initWithOwner(owner: WeakRef): UITableViewRowHeightDelegateImpl { + let delegate = UITableViewRowHeightDelegateImpl.new(); + delegate._owner = owner; + return delegate; + } + + public tableViewWillDisplayCellForRowAtIndexPath(tableView: UITableView, cell: UITableViewCell, indexPath: NSIndexPath) { + let owner = this._owner.get(); + if (owner && (indexPath.row === owner.items.length - 1)) { + owner.notify({ eventName: LOADMOREITEMS, object: owner }); + } + } + + public tableViewWillSelectRowAtIndexPath(tableView: UITableView, indexPath: NSIndexPath): NSIndexPath { + let cell = tableView.cellForRowAtIndexPath(indexPath); + let owner = this._owner.get(); + if (owner) { + notifyForItemAtIndex(owner, cell, cell.view, ITEMTAP, indexPath); + } + cell.highlighted = false; + return indexPath; + } +} + function onSeparatorColorPropertyChanged(data: dependencyObservable.PropertyChangeData) { var bar = data.object; if (!bar.ios) { @@ -163,7 +193,6 @@ export class ListView extends common.ListView { this._ios.registerClassForCellReuseIdentifier(ListViewCell.class(), CELLIDENTIFIER); this._ios.autoresizingMask = UIViewAutoresizing.UIViewAutoresizingNone; this._ios.estimatedRowHeight = DEFAULT_HEIGHT; - this._ios.dataSource = this._dataSource = DataSource.initWithOwner(new WeakRef(this)); this._delegate = UITableViewDelegateImpl.initWithOwner(new WeakRef(this)); this._heights = new Array(); @@ -212,6 +241,23 @@ export class ListView extends common.ListView { this._heights[index] = value; } + public _onRowHeightPropertyChanged(data: dependencyObservable.PropertyChangeData) { + if (data.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._delegate = UITableViewRowHeightDelegateImpl.initWithOwner(new WeakRef(this)); + } + if (this.isLoaded) { + this._nativeView.delegate = this._delegate; + } + super._onRowHeightPropertyChanged(data); + } + public requestLayout(): void { // When preparing cell don't call super - no need to invalidate our measure when cell desiredSize is changed. if (!this._preparingCell) {