@@ -15,19 +15,27 @@ import {
1515 minWidthProperty , minHeightProperty , widthProperty , heightProperty ,
1616 marginLeftProperty , marginTopProperty , marginRightProperty , marginBottomProperty ,
1717 rotateProperty , scaleXProperty , scaleYProperty , translateXProperty , translateYProperty ,
18- zIndexProperty , backgroundInternalProperty
18+ zIndexProperty , backgroundInternalProperty , androidElevationProperty , androidDynamicElevationOffsetProperty
1919} from "../../styling/style-properties" ;
2020
2121import { Background , ad as androidBackground } from "../../styling/background" ;
2222import { profile } from "../../../profiling" ;
2323import { topmost } from "../../frame/frame-stack" ;
2424import { AndroidActivityBackPressedEventData , android as androidApp } from "../../../application" ;
25+ import { device } from "../../../platform" ;
26+ import lazy from "../../../utils/lazy" ;
2527
2628export * from "./view-common" ;
2729
2830const DOMID = "_domId" ;
2931const androidBackPressedEvent = "androidBackPressed" ;
3032
33+ const shortAnimTime = 17694720 ; // android.R.integer.config_shortAnimTime
34+ const statePressed = 16842919 ; // android.R.attr.state_pressed
35+ const stateEnabled = 16842910 ; // android.R.attr.state_enabled
36+
37+ const sdkVersion = lazy ( ( ) => parseInt ( device . sdkVersion ) ) ;
38+
3139const modalMap = new Map < number , DialogOptions > ( ) ;
3240
3341let TouchListener : TouchListener ;
@@ -255,6 +263,8 @@ export class View extends ViewCommon {
255263 private layoutChangeListener : android . view . View . OnLayoutChangeListener ;
256264 private _manager : android . support . v4 . app . FragmentManager ;
257265 private _rootManager : android . support . v4 . app . FragmentManager ;
266+ private _originalElevation : number ;
267+ private _originalStateListAnimator : any ; /* android.animation.StateListAnimator; */
258268
259269 nativeViewProtected : android . view . View ;
260270
@@ -709,6 +719,74 @@ export class View extends ViewCommon {
709719 this . nativeViewProtected . setAlpha ( float ( value ) ) ;
710720 }
711721
722+ [ androidElevationProperty . getDefault ] ( ) : number {
723+ if ( sdkVersion ( ) < 21 ) {
724+ return 0 ;
725+ }
726+
727+ // NOTE: overriden in Button implementation as for widgets with StateListAnimator (Button)
728+ // nativeView.getElevation() returns 0 at the time of the getDefault() query
729+ return layout . toDeviceIndependentPixels ( ( < any > this . nativeViewProtected ) . getElevation ( ) ) ;
730+ }
731+ [ androidElevationProperty . setNative ] ( value : number ) {
732+ if ( sdkVersion ( ) < 21 ) {
733+ return ;
734+ }
735+
736+ this . refreshStateListAnimator ( ) ;
737+ }
738+
739+ [ androidDynamicElevationOffsetProperty . getDefault ] ( ) : number {
740+ return 0 ;
741+ }
742+ [ androidDynamicElevationOffsetProperty . setNative ] ( value : number ) {
743+ if ( sdkVersion ( ) < 21 ) {
744+ return ;
745+ }
746+
747+ this . refreshStateListAnimator ( ) ;
748+ }
749+
750+ private refreshStateListAnimator ( ) {
751+ const nativeView : any = this . nativeViewProtected ;
752+
753+ const ObjectAnimator = android . animation . ObjectAnimator ;
754+ const AnimatorSet = android . animation . AnimatorSet ;
755+
756+ const duration = nativeView . getContext ( ) . getResources ( ) . getInteger ( shortAnimTime ) / 2 ;
757+ const elevation = layout . toDevicePixels ( this . androidElevation || 0 ) ;
758+ const z = layout . toDevicePixels ( 0 ) ;
759+ const pressedZ = layout . toDevicePixels ( this . androidDynamicElevationOffset || 0 ) ;
760+
761+ const pressedSet = new AnimatorSet ( ) ;
762+ pressedSet . playTogether ( java . util . Arrays . asList ( [
763+ ObjectAnimator . ofFloat ( nativeView , "translationZ" , [ pressedZ ] )
764+ . setDuration ( duration ) ,
765+ ObjectAnimator . ofFloat ( nativeView , "elevation" , [ elevation ] )
766+ . setDuration ( 0 ) ,
767+ ] ) ) ;
768+
769+ const notPressedSet = new AnimatorSet ( ) ;
770+ notPressedSet . playTogether ( java . util . Arrays . asList ( [
771+ ObjectAnimator . ofFloat ( nativeView , "translationZ" , [ z ] )
772+ . setDuration ( duration ) ,
773+ ObjectAnimator . ofFloat ( nativeView , "elevation" , [ elevation ] )
774+ . setDuration ( 0 ) ,
775+ ] ) ) ;
776+
777+ const defaultSet = new AnimatorSet ( ) ;
778+ defaultSet . playTogether ( java . util . Arrays . asList ( [
779+ ObjectAnimator . ofFloat ( nativeView , "translationZ" , [ 0 ] ) . setDuration ( 0 ) ,
780+ ObjectAnimator . ofFloat ( nativeView , "elevation" , [ 0 ] ) . setDuration ( 0 ) ,
781+ ] ) ) ;
782+
783+ const stateListAnimator = new ( < any > android . animation ) . StateListAnimator ( ) ;
784+ stateListAnimator . addState ( [ statePressed , stateEnabled ] , pressedSet ) ;
785+ stateListAnimator . addState ( [ stateEnabled ] , notPressedSet ) ;
786+ stateListAnimator . addState ( [ ] , defaultSet ) ;
787+ nativeView . setStateListAnimator ( stateListAnimator ) ;
788+ }
789+
712790 [ horizontalAlignmentProperty . getDefault ] ( ) : HorizontalAlignment {
713791 return < HorizontalAlignment > org . nativescript . widgets . ViewHelper . getHorizontalAlignment ( this . nativeViewProtected ) ;
714792 }
@@ -946,7 +1024,7 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO
9461024 const { getter, setter, auto = 0 } = options ;
9471025 let setPixels , getPixels , setPercent ;
9481026 if ( getter ) {
949- View . prototype [ getter ] = function ( this : View ) : PercentLength {
1027+ View . prototype [ getter ] = function ( this : View ) : PercentLength {
9501028 if ( options ) {
9511029 setPixels = options . setPixels ;
9521030 getPixels = options . getPixels ;
@@ -962,7 +1040,7 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO
9621040 }
9631041 }
9641042 if ( setter ) {
965- View . prototype [ setter ] = function ( this : View , length : PercentLength ) {
1043+ View . prototype [ setter ] = function ( this : View , length : PercentLength ) {
9661044 if ( options ) {
9671045 setPixels = options . setPixels ;
9681046 getPixels = options . getPixels ;
0 commit comments