11import type { Point , Position } from './view-interfaces' ;
22import type { GestureTypes , GestureEventData } from '../../gestures' ;
33import { getNativeScriptGlobals } from '../../../globals/global-utils' ;
4- import { ViewCommon , isEnabledProperty , originXProperty , originYProperty , isUserInteractionEnabledProperty , testIDProperty , AndroidHelper , statusBarStyleProperty } from './view-common' ;
4+ import { ViewCommon , isEnabledProperty , originXProperty , originYProperty , isUserInteractionEnabledProperty , testIDProperty , AndroidHelper , androidOverflowEdgeProperty , statusBarStyleProperty } from './view-common' ;
55import { paddingLeftProperty , paddingTopProperty , paddingRightProperty , paddingBottomProperty } from '../../styling/style-properties' ;
66import { Length } from '../../styling/length-shared' ;
77import { layout } from '../../../utils' ;
@@ -320,6 +320,121 @@ function getModalOptions(domId: number): DialogOptions {
320320 return modalMap . get ( domId ) ;
321321}
322322
323+ const INSET_LEFT = 0 ;
324+ const INSET_TOP = 4 ;
325+ const INSET_RIGHT = 8 ;
326+ const INSET_BOTTOM = 12 ;
327+ const INSET_LEFT_CONSUMED = 16 ;
328+ const INSET_TOP_CONSUMED = 20 ;
329+ const INSET_RIGHT_CONSUMED = 24 ;
330+ const INSET_BOTTOM_CONSUMED = 28 ;
331+
332+ const OverflowEdgeIgnore = - 1 ;
333+ const OverflowEdgeNone : number = 0 ;
334+ const OverflowEdgeLeft : number = 1 << 1 ;
335+ const OverflowEdgeTop : number = 1 << 2 ;
336+ const OverflowEdgeRight : number = 1 << 3 ;
337+ const OverflowEdgeBottom : number = 1 << 4 ;
338+ const OverflowEdgeDontApply : number = 1 << 5 ;
339+ const OverflowEdgeLeftDontConsume : number = 1 << 6 ;
340+ const OverflowEdgeTopDontConsume : number = 1 << 7 ;
341+ const OverflowEdgeRightDontConsume : number = 1 << 8 ;
342+ const OverflowEdgeBottomDontConsume : number = 1 << 9 ;
343+ const OverflowEdgeAllButLeft : number = 1 << 10 ;
344+ const OverflowEdgeAllButTop : number = 1 << 11 ;
345+ const OverflowEdgeAllButRight : number = 1 << 12 ;
346+ const OverflowEdgeAllButBottom : number = 1 << 13 ;
347+
348+ class Inset {
349+ private view : DataView ;
350+ private data : ArrayBuffer ;
351+ constructor ( data : java . nio . ByteBuffer ) {
352+ this . data = ( < any > ArrayBuffer ) . from ( data ) ;
353+ this . view = new DataView ( this . data ) ;
354+ }
355+
356+ public get left ( ) : number {
357+ return this . view . getInt32 ( INSET_LEFT , true ) ;
358+ }
359+
360+ public set left ( value : number ) {
361+ this . view . setInt32 ( INSET_LEFT , value , true ) ;
362+ }
363+
364+ public get top ( ) : number {
365+ return this . view . getInt32 ( INSET_TOP , true ) ;
366+ }
367+
368+ public set top ( value : number ) {
369+ this . view . setInt32 ( INSET_TOP , value , true ) ;
370+ }
371+
372+ public get right ( ) : number {
373+ return this . view . getInt32 ( INSET_RIGHT , true ) ;
374+ }
375+
376+ public set right ( value : number ) {
377+ this . view . setInt32 ( INSET_RIGHT , value , true ) ;
378+ }
379+
380+ public get bottom ( ) : number {
381+ return this . view . getInt32 ( INSET_BOTTOM , true ) ;
382+ }
383+
384+ public set bottom ( value : number ) {
385+ this . view . setInt32 ( INSET_BOTTOM , value , true ) ;
386+ }
387+
388+ public get leftConsumed ( ) : boolean {
389+ return this . view . getInt32 ( INSET_LEFT_CONSUMED , true ) > 0 ;
390+ }
391+
392+ public set leftConsumed ( value : boolean ) {
393+ this . view . setInt32 ( INSET_LEFT_CONSUMED , value ? 1 : 0 , true ) ;
394+ }
395+
396+ public get topConsumed ( ) : boolean {
397+ return this . view . getInt32 ( INSET_TOP_CONSUMED , true ) > 0 ;
398+ }
399+
400+ public set topConsumed ( value : boolean ) {
401+ this . view . setInt32 ( INSET_TOP_CONSUMED , value ? 1 : 0 , true ) ;
402+ }
403+
404+ public get rightConsumed ( ) : boolean {
405+ return this . view . getInt32 ( INSET_RIGHT_CONSUMED , true ) > 0 ;
406+ }
407+
408+ public set rightConsumed ( value : boolean ) {
409+ this . view . setInt32 ( INSET_RIGHT_CONSUMED , value ? 1 : 0 , true ) ;
410+ }
411+
412+ public get bottomConsumed ( ) : boolean {
413+ return this . view . getInt32 ( INSET_BOTTOM_CONSUMED , true ) > 0 ;
414+ }
415+
416+ public set bottomConsumed ( value : boolean ) {
417+ this . view . setInt32 ( INSET_BOTTOM_CONSUMED , value ? 1 : 0 , true ) ;
418+ }
419+
420+ toString ( ) {
421+ return `Inset: left=${ this . left } , top=${ this . top } , right=${ this . right } , bottom=${ this . bottom } , ` + `leftConsumed=${ this . leftConsumed } , topConsumed=${ this . topConsumed } , ` + `rightConsumed=${ this . rightConsumed } , bottomConsumed=${ this . bottomConsumed } ` ;
422+ }
423+
424+ toJSON ( ) {
425+ return {
426+ left : this . left ,
427+ top : this . top ,
428+ right : this . right ,
429+ bottom : this . bottom ,
430+ leftConsumed : this . leftConsumed ,
431+ topConsumed : this . topConsumed ,
432+ rightConsumed : this . rightConsumed ,
433+ bottomConsumed : this . bottomConsumed ,
434+ } ;
435+ }
436+ }
437+
323438export class View extends ViewCommon {
324439 public static androidBackPressedEvent = androidBackPressedEvent ;
325440
@@ -330,6 +445,8 @@ export class View extends ViewCommon {
330445 private layoutChangeListenerIsSet : boolean ;
331446 private layoutChangeListener : android . view . View . OnLayoutChangeListener ;
332447 private _rootManager : androidx . fragment . app . FragmentManager ;
448+ private insetListenerIsSet : boolean ;
449+ private needsInsetListener : boolean ;
333450
334451 nativeViewProtected : android . view . View ;
335452
@@ -348,6 +465,12 @@ export class View extends ViewCommon {
348465 if ( this . isLoaded && ! this . layoutChangeListenerIsSet && isLayoutEvent ) {
349466 this . setOnLayoutChangeListener ( ) ;
350467 }
468+
469+ const isInsetEvent = typeof eventNames === 'string' ? eventNames . indexOf ( ViewCommon . androidOverflowInsetEvent ) !== - 1 : false ;
470+ // only avaiable on LayoutBase
471+ if ( ! this . insetListenerIsSet && isInsetEvent ) {
472+ this . setInsetListener ( ) ;
473+ }
351474 }
352475
353476 removeEventListener ( eventNames : string , callback ?: ( data : EventData ) => void , thisArg ?: any ) {
@@ -359,6 +482,43 @@ export class View extends ViewCommon {
359482 this . nativeViewProtected . removeOnLayoutChangeListener ( this . layoutChangeListener ) ;
360483 this . layoutChangeListenerIsSet = false ;
361484 }
485+
486+ const isInsetEvent = typeof eventNames === 'string' ? eventNames . indexOf ( ViewCommon . androidOverflowInsetEvent ) !== - 1 : false ;
487+
488+ if ( this . insetListenerIsSet && isInsetEvent && this . nativeViewProtected && ( this . nativeViewProtected as any ) . setInsetListener ) {
489+ ( this . nativeViewProtected as any ) . setInsetListener ( null ) ;
490+ this . insetListenerIsSet = false ;
491+ }
492+ }
493+
494+ private setInsetListener ( ) {
495+ if ( this . nativeViewProtected ) {
496+ if ( ( this . nativeViewProtected as any ) . setInsetListener ) {
497+ const ref = new WeakRef ( this ) ;
498+ ( this . nativeViewProtected as any ) . setInsetListener (
499+ new org . nativescript . widgets . LayoutBase . WindowInsetListener ( {
500+ onApplyWindowInsets ( param0 ) {
501+ const owner = ref . get ( ) ;
502+ if ( ! owner ) {
503+ return ;
504+ }
505+
506+ const inset = new Inset ( param0 ) ;
507+ const args = {
508+ eventName : ViewCommon . androidOverflowInsetEvent ,
509+ object : this ,
510+ inset,
511+ } ;
512+ owner . notify ( args ) ;
513+ } ,
514+ } ) ,
515+ ) ;
516+ this . insetListenerIsSet = true ;
517+ }
518+ this . needsInsetListener = false ;
519+ } else {
520+ this . needsInsetListener = true ;
521+ }
362522 }
363523
364524 public _getChildFragmentManager ( ) : androidx . fragment . app . FragmentManager {
@@ -419,6 +579,35 @@ export class View extends ViewCommon {
419579 return manager ;
420580 }
421581
582+ [ androidOverflowEdgeProperty . setNative ] ( value : CoreTypes . AndroidOverflow ) {
583+ const nativeView = this . nativeViewProtected as any ;
584+ if ( typeof value !== 'string' || nativeView === null || nativeView == undefined ) {
585+ return ;
586+ }
587+
588+ if ( ! ( 'setOverflowEdge' in nativeView ) ) {
589+ return ;
590+ }
591+
592+ switch ( value ) {
593+ case 'none' :
594+ nativeView . setOverflowEdge ( OverflowEdgeNone ) ;
595+ break ;
596+ case 'ignore' :
597+ nativeView . setOverflowEdge ( OverflowEdgeIgnore ) ;
598+ break ;
599+ default :
600+ {
601+ const edge = parseEdges ( value ) ;
602+
603+ if ( edge != null ) {
604+ nativeView . setOverflowEdge ( edge ) ;
605+ }
606+ }
607+ break ;
608+ }
609+ }
610+
422611 @profile
423612 public onLoaded ( ) {
424613 this . _manager = null ;
@@ -468,6 +657,10 @@ export class View extends ViewCommon {
468657 if ( this . needsOnLayoutChangeListener ( ) ) {
469658 this . setOnLayoutChangeListener ( ) ;
470659 }
660+
661+ if ( ! this . insetListenerIsSet && this . needsInsetListener ) {
662+ this . setInsetListener ( ) ;
663+ }
471664 }
472665
473666 public needsOnLayoutChangeListener ( ) {
@@ -1356,8 +1549,43 @@ export class View extends ViewCommon {
13561549 }
13571550}
13581551
1552+ const edgeMap : Record < string , number > = {
1553+ none : OverflowEdgeNone ,
1554+ left : OverflowEdgeLeft ,
1555+ top : OverflowEdgeTop ,
1556+ right : OverflowEdgeRight ,
1557+ bottom : OverflowEdgeBottom ,
1558+ 'dont-apply' : OverflowEdgeDontApply ,
1559+ 'left-dont-consume' : OverflowEdgeLeftDontConsume ,
1560+ 'top-dont-consume' : OverflowEdgeTopDontConsume ,
1561+ 'right-dont-consume' : OverflowEdgeRightDontConsume ,
1562+ 'bottom-dont-consume' : OverflowEdgeBottomDontConsume ,
1563+ 'all-but-left' : OverflowEdgeAllButLeft ,
1564+ 'all-but-top' : OverflowEdgeAllButTop ,
1565+ 'all-but-right' : OverflowEdgeAllButRight ,
1566+ 'all-but-bottom' : OverflowEdgeAllButBottom ,
1567+ } ;
1568+
1569+ function parseEdges ( edges : string ) : number | null {
1570+ let result = 0 ;
1571+ const values = edges . split ( ',' ) ;
1572+ for ( const raw of values ) {
1573+ const value = edgeMap [ raw . trim ( ) ] ;
1574+ if ( value === undefined ) continue ;
1575+ // dont-apply overrides everything else
1576+ if ( value === OverflowEdgeDontApply ) return value ;
1577+ result |= value ;
1578+ }
1579+ return result === 0 ? null : result ;
1580+ }
1581+
13591582export class ContainerView extends View {
13601583 public iosOverflowSafeArea : boolean ;
1584+
1585+ constructor ( ) {
1586+ super ( ) ;
1587+ this . androidOverflowEdge = 'none' ;
1588+ }
13611589}
13621590
13631591export class CustomLayoutView extends ContainerView {
0 commit comments