Search code examples
nativescriptnativescript-vue

UIScrollView with fade effect with nativescript vuejs


I would like to know if it's possible to have UIScrollView with fade effect with nativescript please ?

For example : https://medium.com/@luisfmachado/uiscrollview-with-fade-effect-246e332e8b24

I read the documentation https://nativescript-vue.org/en/docs/elements/components/scroll-view/, but I don't found this information.

I would like this result for example :

enter image description here

Do you have an idea please ? Thank you

I have no idea how can I put the native code in my component

<template>
    <ScrollView class="scroll" orientation="vertical" row="1" ref="scrollView">
        <StackLayout marginLeft="10" marginRight="10" class="container-verses">
            <StackLayout horizontalAlignment="center">
                <Label textWrap="true" textAlignment="center" text="hello" color="#FFFFFF" fontSize="20"/>
                ...
                <Label textWrap="true" textAlignment="center" text="hello" color="#FFFFFF" fontSize="20"/>
            </StackLayout>
        </StackLayout>
    </ScrollView>
</template>

<script>
    export default {
        name    : 'FadeScrollView',
        computed: {},
        methods : {
            //
        }
    };
</script>

<style lang='scss' scoped>

</style>

Solution

  • Here is how you translate Swift into NativeScript

    import { isIOS } from "@nativescript/core/platform";
    import { ScrollView } from "@nativescript/core/ui/scroll-view";
    
    let FadeScrollViewImpl;
    
    if (isIOS) {
        FadeScrollViewImpl = UIScrollView.extend({
            fadePercentage: 0.2,
            gradientLayer: CAGradientLayer.new(),
            transparentColor: UIColor.clearColor.CGColor,
            opaqueColor: UIColor.blackColor.CGColor,
    
            topOpacity: () => {
                const scrollViewHeight = this.frame.size.height;
                const scrollContentSizeHeight = this.contentSize.height;
                const scrollOffset = this.contentOffset.y;
                const alpha = (scrollViewHeight >= scrollContentSizeHeight || scrollOffset <= 0) ? 1 : 0;
                return UIColor.alloc().initWithWhiteAlpha(0, alpha).CGColor;
            },
    
            bottomOpacity: () => {
                const scrollViewHeight = this.frame.size.height;
                const scrollContentSizeHeight = this.contentSize.height;
                const scrollOffset = this.contentOffset.y;
                const alpha = (scrollViewHeight >= scrollContentSizeHeight || scrollOffset + scrollViewHeight >= scrollContentSizeHeight) ? 1 : 0
                return UIColor.alloc().initWithWhiteAlpha(0, alpha).CGColor;
            },
    
            layoutSubviews() {
                super.layoutSubviews()
    
                this.delegate = this;
                const maskLayer = CALayer.new();
                maskLayer.frame = this.bounds;
    
                this.gradientLayer.frame = CGRectMake(this.bounds.origin.x, 0, this.bounds.size.width, this.bounds.size.height);
                this.gradientLayer.colors = [this.topOpacity, this.opaqueColor, this.opaqueColor, this.bottomOpacity];
                this.gradientLayer.locations = [0, NSNumber.alloc().initWithFloat(this.fadePercentage), NSNumber.alloc().initWithFloat(1 - this.fadePercentage), 1];
                maskLayer.addSublayer(this.gradientLayer);
    
                this.layer.mask = maskLayer
            },
    
            scrollViewDidScroll(scrollView) {
                this.gradientLayer.colors = [topOpacity, opaqueColor, opaqueColor, bottomOpacity];
            }
        });
    }
    
    export class FadeScrollView extends ScrollView {
        createNativeView() {
            if (isIOS) {
                return FadeScrollViewImpl.new();
            } else {
                return super.createNativeView();
            }
        }
    
        attachNative() {
            if (!isIOS) {
                super.attachNative();
            }
        }
    }
    

    Then you just have to register the element to start using it in template

    Vue.registerElement('FadeScrollView', () => require('./fade-scrollView').FadeScrollView)
    

    Playground Sample