Repository: NativeScript/NativeScript
File: tns-core-modules/ui/core/view/view.android.ts (TypeScript)

Code before:
            if (this._originalElevation === undefined) {
                this._originalElevation = nativeView.getElevation();
            }
            nativeView.setElevation(layout.toDevicePixels(value));
        } else {
            // reset to original value
            if (this._originalElevation !== undefined) {
                nativeView.setElevation(this._originalElevation);
            }
        }
        this._refreshStateListAnimator();
    }

    [androidPressedZProperty.getDefault](): number {
        console.log("androidPressedZProperty.getDefault");
        return undefined;
    }

    [androidPressedZProperty.setNative](value: number) {
        if (sdkVersion() < 21) { return; }
        console.log("androidPressedZProperty.setNative, value: " + value);
        this._refreshStateListAnimator();

    }

    _refreshStateListAnimator() {
        const nativeView: any = this.nativeViewProtected;
        // we have elevation or pressedZ
        if (this._originalStateListAnimator === undefined) {
            this._originalStateListAnimator = nativeView.getStateListAnimator();
        }
        const style = this.style;
        console.log("refreshing sla", this.elevation, this.androidPressedZ, this._originalStateListAnimator, elevationProperty.isSet(style), androidPressedZProperty.isSet(style));
        if ((!elevationProperty.isSet(style) && !androidPressedZProperty.isSet(style)) || // nothing to override
            (!androidPressedZProperty.isSet(style) && this._originalStateListAnimator === null)) { // we don't need pressedZ and there's no default
            // we have no reason to override anything, reset to default
            if (this._originalStateListAnimator !== nativeView.getStateListAnimator()) {
                nativeView.setStateListAnimator(this._originalStateListAnimator);
            }
            this._originalStateListAnimator = undefined;
            return;
        }
        const sla = new (android.animation as any).StateListAnimator();

        const ObjectAnimator = android.animation.ObjectAnimator;
        const AnimatorSet = android.animation.AnimatorSet;
        const shortAnimTime = android.R.integer.config_shortAnimTime;

        const buttonDuration =
            nativeView.getContext().getResources().getInteger(shortAnimTime) / 2;
        const pressedElevation = layout.toDevicePixels(this.elevation || 0);

Review comment (suggestion):
I was testing the outline button scenario with this markup (btn and btn-outline are classes from nativescript-theme-core):
``` xml
<Button class="btn btn-outline" text="tap" tap="onTap" />
```
But it does not work out-of-the-box despite default elevation is set to 0.

This works:
``` xml
<Button class="btn btn-outline" elevation="0" text="tap" tap="onTap" />
```

Code after:
        // nativeView.getElevation() returns 0 at the time of the getDefault() query
        return layout.toDeviceIndependentPixels((<any>this.nativeViewProtected).getElevation());
    }
    [androidElevationProperty.setNative](value: number) {
        if (sdkVersion() < 21) {
            return;
        }

        this.refreshStateListAnimator();
    }

    [androidDynamicElevationOffsetProperty.getDefault](): number {
        return 0;
    }
    [androidDynamicElevationOffsetProperty.setNative](value: number) {
        if (sdkVersion() < 21) {
            return;
        }

        this.refreshStateListAnimator();
    }

    private refreshStateListAnimator() {
        const nativeView: any = this.nativeViewProtected;

        const ObjectAnimator = android.animation.ObjectAnimator;
        const AnimatorSet = android.animation.AnimatorSet;

        const duration = nativeView.getContext().getResources().getInteger(shortAnimTime) / 2;
        const elevation = layout.toDevicePixels(this.androidElevation || 0);
        const z = layout.toDevicePixels(0);
        const pressedZ = layout.toDevicePixels(this.androidDynamicElevationOffset || 0);

        const pressedSet = new AnimatorSet();
        pressedSet.playTogether(java.util.Arrays.asList([
            ObjectAnimator.ofFloat(nativeView, "translationZ", [pressedZ])
                .setDuration(duration),
            ObjectAnimator.ofFloat(nativeView, "elevation", [elevation])
                .setDuration(0),
        ]));

        const notPressedSet = new AnimatorSet();
        notPressedSet.playTogether(java.util.Arrays.asList([
            ObjectAnimator.ofFloat(nativeView, "translationZ", [z])
                .setDuration(duration),
            ObjectAnimator.ofFloat(nativeView, "elevation", [elevation])
                .setDuration(0),
        ]));

        const defaultSet = new AnimatorSet();
        defaultSet.playTogether(java.util.Arrays.asList([