Arigarasuthan
Arigarasuthan

Reputation: 373

How to access UIScrollview delegates from native ios in nativescript angular?

Iam working the android and ios application using nativescript angular application.i want to access the scrollview delegates of the ios,i was accessed the scrollview delegates from the native ios following code.but it was not working:

My scrollview delegate implementation class:

// import {Injectable, EventEmitter,Output} from "@angular/core";
@ObjCClass(UIScrollViewDelegate)
 export class FoodScrollDelegate extends NSObject implements UIScrollViewDelegate
{
    public static ObjCProtocols = [UIScrollViewDelegate];
    // @Output() yvalue:EventEmitter<any>=new EventEmitter();
    private _originalDelegate:UIScrollViewDelegate;
    public getY:Number=0;
     constructor()
     {
         super();
     }

    public static initWithOriginalDelegate(originalDelegate:UIScrollViewDelegate):FoodScrollDelegate{
        console.log("Called Method");
        let delegate=<FoodScrollDelegate>FoodScrollDelegate.new();
        delegate._originalDelegate=originalDelegate;
        return delegate;
    }


}

I have setting the scrollview delegate like this:

onScrollLoaded(args)
{
    var subscroll=args.object;
    var uiscrollview=subscroll.ios;
    let tf=<any>this.subMenuScroll;
    var newweakref=new WeakRef(uiscrollview);
    const newDelegate=FoodScrollDelegate.initWithOriginalDelegate(tf._delegate);
    console.log("PrintDelegate",+newDelegate);
    uiscrollview.delegate=newDelegate;    

}

My MenuComponet class Like this:

 import { Component, OnInit, AfterViewInit,ViewChild, ElementRef} from "@angular/core";
import {Page, borderTopRightRadiusProperty} from "ui/page";
import { isIOS, isAndroid } from 'tns-core-modules/platform';
import { RadListView, ListViewEventData } from "nativescript-ui-listview";
import { RestaurentMenuModel,RestaurentSubMenuModel } from "~/app/models/restaurant";
import { ObservableArray } from "tns-core-modules/data/observable-array";
import { run } from "tns-core-modules/application/application";
import { ScrollEventData, ScrollView } from "tns-core-modules/ui/scroll-view/scroll-view";
import { RouterExtensions } from "nativescript-angular/router";
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout/stack-layout";
import { Label } from "tns-core-modules/ui/label/label";
import { analyzeAndValidateNgModules } from "@angular/compiler";
import * as utils from "tns-core-modules/utils/utils";
import { setTimeout } from "tns-core-modules/timer";
import { EventData } from "data/observable";
import { FoodScrollDelegate } from "~/app/Utils/scroll_delegate";

declare var UITableViewCellSelectionStyle;
declare var UIView, NSMutableArray, NSIndexPath;

//declare var setShowsHorizontalScrollIndicator;



@Component({
    selector:"restaurant_menu",
    moduleId:module.id,
    templateUrl:"./restaurant_menu.component.html",
    styleUrls:["./restaurant_menu.component.css"],
})

export class RestaurantMenu  implements OnInit
{


    //public cartCount:Number=1;
    @ViewChild("ScrollList") scrollList:ElementRef;
    @ViewChild("categoryList") categoryList:ElementRef;
    public AllMenuList:any;
    public cartTotal:any=0;
    public cartItem:any=0;
    public isCartVisible=false;
     incrementItem:any=0;
     decrementItem:any=0;
     categoryContainer:Label;
     subMenuContainers:StackLayout;
     offsetValue:any=0;
     dummyStatus:any=0;
     horizontalOffsetvalue:any=0;
     lengthHorizontaloffsetLength:any=0;   
     public selectedIndex:Number=0;
     public scrollEnabled:Boolean=false;
     lastItemY:Number=0;
     subMenuScroll:ScrollView;
     foodScrollDelegate:FoodScrollDelegate;
    _delegate:any;
    constructor(private page:Page,public routerExtension:RouterExtensions)
    {

    }
    ngOnInit()
    {
        this.subMenuScroll=this.page.getViewById("subMenuScroll");
        //this.subMenuScroll.ios.delegate=FoodScrollDelegate.initWithOriginalDelegate(this._delegate);
       //console.log("PrintDelegate"+this.foodScrollDelegate.scrollViewDidEndDraggingWillDecelerate);
    //    this.foodScrollDelegate=new FoodScrollDelegate();
    //    this.foodScrollDelegate.yvalue.subscribe(yvalue=>{
    //         console.log("TheYYValue"+yvalue);
    //     });


    }
    public scrollViewDidEndDraggingWillDecelerate?(scrollView: UIScrollView, decelerate: boolean): void {
            console.log("WillScrollEnd"+" "+decelerate);
        }
    public scrollViewDidScroll?(scrollView: UIScrollView): void {
            this.getY=scrollView.contentOffset.y;
            console.log("Yposition"+this.getY);
            //this.yvalue.emit(this.getY);
        }
    onLoaded(event)
    {
        const scrollview = event.object;
        if (scrollview.ios) {
            scrollview.ios.showsHorizontalScrollIndicator = false;
        }
        else
        {
            scrollview.android.setHorizontalScrollBarEnabled(false);
        }
    }

    onNavBtnTap()
    {
        this.routerExtension.backToPreviousPage();
    }


}

Inside the i was implemented the delegate methods.but it was working

Upvotes: 2

Views: 615

Answers (1)

Manoj
Manoj

Reputation: 21908

ObjCClass is an alternative syntax for ObjCProtocols. You may not need to do both.

The default delegate is attached after loaded event, so your delegate may be overwritten again. You will have to extend the ScrollView and override the attachNative method.

class MyScrollView extends ScrollView {
    protected attachNative() {
        (<any>ScrollView.prototype).attachNative.call(this);
        if (isIOS) {
            (<any>this)._delegate = FoodScrollDelegate.initWithOriginalDelegate((<any>this)._delegate);
            this.nativeViewProtected.delegate = (<any>this)._delegate;
        }
    }
}

Register this MyScrollView,

registerElement("MyScrollView", () => MyScrollView);

Now you should be able to use MyScrollView instead of ScrollView in your HTML which will override the default delegate. If you wanted to override delegate for all ScrollView used in app, you could simply override the prototype chain of ScrollView conditionally on iOS.

(<any>ScrollView.prototype).originalAttachNative = (<any>ScrollView.prototype).attachNative;
(<any>ScrollView.prototype).attachNative = function () {
    this.originalAttachNative();
    const newDelegate = FoodScrollDelegate.initWithOriginalDelegate(this._delegate);
    this._delegate = newDelegate;
    this.nativeViewProtected.delegate = newDelegate;
};

If you like to fire an event from delegate then,

   scrollViewDidEndDraggingWillDecelerate(scrollView: UIScrollView, decelerate: boolean) {
        const owner = (<WeakRef<ScrollView>>(<any>this._originalDelegate)._owner).get();
        if (owner) {
            owner.notify({
                object: owner,
                eventName: "dragEnd",
                decelerate: decelerate
            });
        }
    }

Now from Angular, you could listen to the event,

HTML

(dragEnd)="onDragEnd($event)"

TS

onDragEnd(event) {
   console.log(event.decelerate);
}

Upvotes: 2

Related Questions