mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-06 17:28:29 +08:00
feat(ios): searchAutoHide wip
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo" class="page">
|
||||
<Page.actionBar>
|
||||
<ActionBar title="Dev Toolbox" icon="" class="action-bar" iosLargeTitle="true" iosShadow="false">
|
||||
<ActionBar title="Dev Toolbox" icon="" class="action-bar">
|
||||
</ActionBar>
|
||||
</Page.actionBar>
|
||||
<StackLayout>
|
||||
|
@ -8,6 +8,7 @@
|
||||
<GridLayout backgroundColor="#efefef">
|
||||
<ListView class="list-group" items="{{ countries }}" itemTap="{{ componentsItemTap }} " separatorColor="#00000000" itemTemplateSelector="{{ selectItemTemplate }}" stickyHeader="true" sectioned="true" stickyHeaderTopPadding="false" stickyHeaderTemplate="<GridLayout><Label text='{{ title }}' fontSize='18' fontWeight='bold' color='#009bff' padding='8 0 8 12' borderBottomWidth='1' borderBottomColor='#ccc' borderTopWidth='1' borderTopColor='#ccc' backgroundColor='#fff' /></GridLayout>" stickyHeaderHeight="45" itemLoading="{{ itemLoading }}"
|
||||
showSearch="true"
|
||||
searchAutoHide="true"
|
||||
searchChange="{{ onSearchTextChange }}">
|
||||
<ListView.itemTemplates>
|
||||
<template key="main">
|
||||
|
15
packages/core/ui/list-view/index.d.ts
vendored
15
packages/core/ui/list-view/index.d.ts
vendored
@ -146,7 +146,7 @@ export class ListView extends View {
|
||||
sectioned: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets a value indicating whether the ListView should show a search bar.
|
||||
* Gets or sets whether search functionality is enabled.
|
||||
* When enabled on iOS, uses native UISearchController for optimal performance.
|
||||
*
|
||||
* @nsProperty
|
||||
@ -154,6 +154,14 @@ export class ListView extends View {
|
||||
showSearch: boolean;
|
||||
|
||||
/**
|
||||
* Gets or sets whether the search bar should auto-hide when scrolling (iOS only).
|
||||
* When true, the search bar will automatically hide when the user scrolls down
|
||||
* and reappear when scrolling up, using iOS native behavior.
|
||||
* Only applies when showSearch is true and running on iOS with navigation controller.
|
||||
*
|
||||
* @nsProperty
|
||||
*/
|
||||
searchAutoHide: boolean; /**
|
||||
* Forces the ListView to reload all its items.
|
||||
*/
|
||||
refresh();
|
||||
@ -339,3 +347,8 @@ export const sectionedProperty: Property<ListView, boolean>;
|
||||
* Represents the observable property backing the showSearch property of each ListView instance.
|
||||
*/
|
||||
export const showSearchProperty: Property<ListView, boolean>;
|
||||
|
||||
/**
|
||||
* Represents the observable property backing the searchAutoHide property of each ListView instance.
|
||||
*/
|
||||
export const searchAutoHideProperty: Property<ListView, boolean>;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ItemEventData, SearchEventData, ItemsSource } from '.';
|
||||
import { ListViewBase, separatorColorProperty, itemTemplatesProperty, iosEstimatedRowHeightProperty, stickyHeaderProperty, stickyHeaderTemplateProperty, stickyHeaderHeightProperty, sectionedProperty, showSearchProperty } from './list-view-common';
|
||||
import { ListViewBase, separatorColorProperty, itemTemplatesProperty, iosEstimatedRowHeightProperty, stickyHeaderProperty, stickyHeaderTemplateProperty, stickyHeaderHeightProperty, sectionedProperty, showSearchProperty, searchAutoHideProperty } from './list-view-common';
|
||||
import { CoreTypes } from '../../core-types';
|
||||
import { View, KeyedTemplate, Template } from '../core/view';
|
||||
import { Length } from '../styling/length-shared';
|
||||
@ -499,24 +499,41 @@ export class ListView extends ListViewBase {
|
||||
// 2. Tell it who will update results
|
||||
this._searchController.searchResultsUpdater = this._searchDelegate;
|
||||
|
||||
// 3. Don't dim or obscure your table by default
|
||||
// 3. Critical: Don't dim or obscure the table, and prevent extra content
|
||||
this._searchController.obscuresBackgroundDuringPresentation = false;
|
||||
this._searchController.dimsBackgroundDuringPresentation = false;
|
||||
this._searchController.hidesNavigationBarDuringPresentation = false;
|
||||
|
||||
// 4. Placeholder text
|
||||
// 4. Placeholder text and styling
|
||||
this._searchController.searchBar.placeholder = 'Search';
|
||||
this._searchController.searchBar.searchBarStyle = UISearchBarStyle.Minimal;
|
||||
|
||||
// 5. CRITICAL: Make sure the search bar doesn't remain on screen if the user navigates
|
||||
// 5. CRITICAL: Proper presentation context setup
|
||||
const viewController = this._getViewController();
|
||||
if (viewController) {
|
||||
viewController.definesPresentationContext = true;
|
||||
viewController.providesPresentationContextTransitionStyle = true;
|
||||
|
||||
// 6a. If we're in a UINavigationController...
|
||||
// 6a. If we're in a UINavigationController (iOS 11+)...
|
||||
if (SDK_VERSION >= 11.0 && viewController.navigationItem) {
|
||||
viewController.navigationItem.searchController = this._searchController;
|
||||
viewController.navigationItem.hidesSearchBarWhenScrolling = false;
|
||||
|
||||
// Set auto-hide behavior based on searchAutoHide property
|
||||
viewController.navigationItem.hidesSearchBarWhenScrolling = this.searchAutoHide;
|
||||
|
||||
// Optional: Enable large titles for better auto-hide effect when searchAutoHide is true
|
||||
// if (this.searchAutoHide && viewController.navigationController && viewController.navigationController.navigationBar) {
|
||||
// // Only set large titles if not already configured
|
||||
// if (!viewController.navigationController.navigationBar.prefersLargeTitles) {
|
||||
// viewController.navigationController.navigationBar.prefersLargeTitles = true;
|
||||
// }
|
||||
// // Set large title display mode for this specific view controller
|
||||
// if (viewController.navigationItem.largeTitleDisplayMode === UINavigationItemLargeTitleDisplayMode.Automatic) {
|
||||
// viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Always;
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
// 6b. Or just put it at the top of our table
|
||||
// 6b. Fallback: put it at the top of our table
|
||||
this.nativeViewProtected.tableHeaderView = this._searchController.searchBar;
|
||||
}
|
||||
} else {
|
||||
@ -524,11 +541,20 @@ export class ListView extends ListViewBase {
|
||||
this.nativeViewProtected.tableHeaderView = this._searchController.searchBar;
|
||||
}
|
||||
|
||||
// Ensure search bar is properly sized
|
||||
// 7. Ensure search bar is properly sized and prevent content inset issues
|
||||
this._searchController.searchBar.sizeToFit();
|
||||
|
||||
// 8. Disable automatic content inset adjustment that can cause spacing issues
|
||||
if (this.nativeViewProtected.respondsToSelector('setContentInsetAdjustmentBehavior:')) {
|
||||
// iOS 11+ - prevent automatic content inset adjustments
|
||||
this.nativeViewProtected.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
|
||||
} else {
|
||||
// iOS 10 and below - disable automatic content inset
|
||||
this.nativeViewProtected.automaticallyAdjustsScrollIndicatorInsets = false;
|
||||
}
|
||||
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`ListView: UISearchController setup complete`, Trace.categories.Debug);
|
||||
Trace.write(`ListView: UISearchController setup complete with searchAutoHide: ${this.searchAutoHide}`, Trace.categories.Debug);
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,6 +571,15 @@ export class ListView extends ListViewBase {
|
||||
this.nativeViewProtected.tableHeaderView = null;
|
||||
}
|
||||
|
||||
// Reset content inset adjustment behavior
|
||||
if (this.nativeViewProtected.respondsToSelector('setContentInsetAdjustmentBehavior:')) {
|
||||
// iOS 11+ - restore automatic content inset adjustments
|
||||
this.nativeViewProtected.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Automatic;
|
||||
} else {
|
||||
// iOS 10 and below - restore automatic content inset
|
||||
this.nativeViewProtected.automaticallyAdjustsScrollIndicatorInsets = true;
|
||||
}
|
||||
|
||||
// Cleanup references
|
||||
this._searchController.searchResultsUpdater = null;
|
||||
this._searchController = null;
|
||||
@ -1087,4 +1122,32 @@ export class ListView extends ListViewBase {
|
||||
this._cleanupSearchController();
|
||||
}
|
||||
}
|
||||
|
||||
[searchAutoHideProperty.getDefault](): boolean {
|
||||
return false;
|
||||
}
|
||||
[searchAutoHideProperty.setNative](value: boolean) {
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`ListView: searchAutoHide set to ${value}`, Trace.categories.Debug);
|
||||
}
|
||||
|
||||
// If search is already enabled, update the existing search controller
|
||||
if (this.showSearch && this._searchController) {
|
||||
const viewController = this._getViewController();
|
||||
if (viewController && viewController.navigationItem && SDK_VERSION >= 11.0) {
|
||||
viewController.navigationItem.hidesSearchBarWhenScrolling = value;
|
||||
|
||||
// Enable large titles for better auto-hide effect when searchAutoHide is true
|
||||
// if (value && viewController.navigationController && viewController.navigationController.navigationBar) {
|
||||
// if (!viewController.navigationController.navigationBar.prefersLargeTitles) {
|
||||
// viewController.navigationController.navigationBar.prefersLargeTitles = true;
|
||||
// }
|
||||
// if (viewController.navigationItem.largeTitleDisplayMode === UINavigationItemLargeTitleDisplayMode.Automatic) {
|
||||
// viewController.navigationItem.largeTitleDisplayMode = UINavigationItemLargeTitleDisplayMode.Always;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
// If search is not enabled yet, the property will be used when _setupSearchController is called
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ export abstract class ListViewBase extends ContainerView implements ListViewDefi
|
||||
public stickyHeaderTopPadding: boolean;
|
||||
public sectioned: boolean;
|
||||
public showSearch: boolean;
|
||||
public searchAutoHide: boolean;
|
||||
|
||||
get separatorColor(): Color {
|
||||
return this.style.separatorColor;
|
||||
@ -349,3 +350,10 @@ export const showSearchProperty = new Property<ListViewBase, boolean>({
|
||||
valueConverter: booleanConverter,
|
||||
});
|
||||
showSearchProperty.register(ListViewBase);
|
||||
|
||||
export const searchAutoHideProperty = new Property<ListViewBase, boolean>({
|
||||
name: 'searchAutoHide',
|
||||
defaultValue: false,
|
||||
valueConverter: booleanConverter,
|
||||
});
|
||||
searchAutoHideProperty.register(ListViewBase);
|
||||
|
Reference in New Issue
Block a user