I have built an app with NativeScript Angular (now on v4.1). I am using the code below to set a status bar color on Android, which works fine for "regular" views by using angular routing:
if (isAndroid) {
if (app.android && device.sdkVersion >= '21') {
const nativeColor = new Color('purple').android;
const window = app.android.startActivity.getWindow();
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
app.android.startActivity.getWindow().setStatusBarColor(nativeColor);
}
}
However, it does not work in a modal, where the colored status-bar turns to black. Anyone any ideas why this is? My best guess would be that a modal is not referenced by app.android.startActivity.getWindow() but I’m unclear as how to get it.
Not sure to what extent this is related, but also I am unable to set a different loading indicator on iOS in modals by using this code from the docs (again works fine in non-modal views):
if (isIOS) {
var indicator = this.page.getViewById("spinner");
indicator.ios.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge;
}
Thanks for any pointers!
P.S.
Here is a demo project which displays the problem both with the status bar on Android, as well as not being able to set the activity indicator on iOS.
For anyone reading this later on: I had some help on the NativeScript forum and did not yet accomplish setting the statusbar color on the modal, but I was able to span the background under the status bar in the modal component which is good enough for my purposes.
I was also able to change the ActivityIndicator in the modal simply by using an Angular ViewChild on the indicator element instead of finding it through Page (which turns out does not refer to the modal).
import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from "#angular/core";
import { ModalDialogParams } from "nativescript-angular/modal-dialog";
import { isIOS, isAndroid, device } from 'platform';
import * as app from "application";
declare var UIActivityIndicatorViewStyle: any;
declare var android: any;
#Component({
template: `
<StackLayout #root>
<StackLayout orientation="horizontal">
<ActivityIndicator #spinner id="spinner" busy="true"></ActivityIndicator>
<ActivityIndicator busy="true"></ActivityIndicator>
</StackLayout>
</StackLayout>
`
})
export class ModalTest implements OnInit, AfterViewInit {
#ViewChild('root') root: ElementRef;
#ViewChild('spinner') spinner: ElementRef;
constructor(
public modalParams: ModalDialogParams
) {}
public ngOnInit() {
/* show large activity indicator on iOS */
if (isIOS) {
this.spinner.nativeElement.ios.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge;
}
}
public ngAfterViewInit() {
if (isAndroid) {
setTimeout(() => {
if (app.android && device.sdkVersion >= '21') {
const dialog = this.root.nativeElement._dialogFragment.getDialog();
const window = dialog.getWindow();
window.addFlags(android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
},1);
}
}
public closeModal() {
this.modalParams.closeCallback();
}
}
Related
I have been working to create graana.com clone with Vue 3 and Composition API syntax. I want add remove classes to navbar on scroll. If user scrolls downwards we should automatically add a class ("scrolled") to navbar to apply special styles and when screen is scrolled back to top ("scrolled") class is removed.
See example at https://www.graana.com/.
I want to copy their navbar behaviour using Vue 3 Composition API.
Can you help me out?
<header class="header" ref="headRef">
import { defineComponent, ref } from "vue";
import { onMounted } from "#vue/runtime-core";
setup(){
const headRef = ref(null); // obtain the reference
onMounted(() => {
window.addEventListener("scroll", () => {
var curr = window.pageYOffset;
// You can style header-bg for style purpose
if (curr >= 100) {
headRef.value.classList.add("header-bg");
}else{
headRef.value.classList.remove("header-bg");
}
});
});
return {
headRef
}
}
As shown in the image 1 below, when the modal view on ios 13 shows up, the default background is black. But on nativescript, the default background is white as shown in the image 2. How to achieve the image 1 kind of background (black) using nativescript core? I tried changing the color of status bar but that actually changes the color of the top page portion that's partially visible in the images. I tried to define background-color on Frame css, but didn't work. Any suggestions? Thanks in advance.
Image 1:
Image 2:
The modal view options:
const option: ShowModalOptions = {
context: { selectedAccount: account },
closeCallback: (a, b, c, action) => {
//some code
},
fullscreen: false
};
mainView.showModal("./modal-add-page", option);
You have to set the background color of window on iOS.
Update: Nativescript 7
import * as app form "#nativescript/core/application";
import { Color } from "#nativescript/core/color";
import { isIOS } from '#nativescript/core';
if (isIOS) {
if (app.hasLaunched) {
app.ios.window.backgroundColor = new Color("black").ios;
} else {
app.on("launch", _ => app.ios.window.backgroundColor = new Color("black").ios)
}
}
Older versions:
import * as app form "tns-core-modules/application";
import { Color } from "tns-core-modules/color";
// You must run it once application is initiated
app.ios.window.backgroundColor = new Color("black").ios;
Hai am developing android and ios application using native script-angular.I have used a nativescript-drop-down plugin in my app.I have used valuelist array to plot values in the dropdown. But the value list return error like "Property 'push' does not exist on type in ValueList Dropdown".I don't know how this issue arises. Help me to fix the issue.
My Sample code:
My Html:
<StackLayout orientation="vertical">
<DropDown [items>="items"></DropDown>
</StackLayout>
My Component ts file:
import { Component } from "#angular/core";
import {ValueList} from "nativescript-drop-down";
#Component({
selector: "my-app",
templateUrl:"app.component.html",
})
export class AppComponent {
public items:ValueList<string>;
constructor() {
this.items = [];
for(var k=0; k<10; k++)
{
items.push({
value:k,
display:"Hello World"
})
}
}
}
Try this..
you are doing assigning array which is not ValueList bype where as items variable is. So I guess that's what causing the issue.
Consider below code which is mentioned like in the Documentation.
public items: ValueList<string>;
constructor() {
let valueItems = [];
for(var k=0; k<10; k++) {
valueItems.push({
value:k,
display:"Hello World"
});
}
this.items = new ValueList<string>(valueItems);
}
I think you have a typo in Template code..
<StackLayout orientation="vertical">
<DropDown [items]="items"></DropDown>
</StackLayout>
Hope this helps.. :)
I created an app and it does work great but images load every time I scroll up and down, I looked it in google and found this, the problem is I use angular, there is no such thing as viewModel in my angular version, how do I apply cache image into template?
You can try this code. It is working for me.
.ts code
import imageCacheModule = require("ui/image-cache");
import imageSource = require("image-source");
var cache = new imageCacheModule.Cache();
private _imageSrc: any;
private imgSource: any;
getImageCache(imageURL) {
cache.placeholder = imageSource.fromResource("res://no-image.png");
cache.maxRequests = 10;
cache.enableDownload()
var images = cache.get(imageURL)
if(images) {
return images
} else {
cache.push({
key: imageURL,
url: imageURL,
completed: (image: any, key: string) => {
if (imageURL === key) {
this.imgSource = imageSource.fromNativeSource(images);
}
}
})
cache.disableDownload();
}
HTMl code
<Image [src]="getImageCache(item.image?.url)" class="item-image"></Image>
I want to integrate a custom NS core / third party component into an Angular template. The attributes of my component should also be set in the template.
Given the generated sample from tns, i have done the following steps:
Register my Component:
registerElement("TestView", () => require("./test-view").TestView);
Create Component:
import observable = require("data/observable");
import stackLayout = require("ui/layouts/stack-layout");
import label = require("ui/label");
import button = require("ui/button");
import { View } from "ui/core/view";
import { Property, PropertyChangeData, PropertyMetadata, PropertyMetadataSettings } from "ui/core/dependency-observable";
export class TestView extends stackLayout.StackLayout {
public static userNameProperty = new Property(
"userName",
"TestView",
new PropertyMetadata("", PropertyMetadataSettings.None)
);
public get userName(): string {
return this._getValue(TestView.userNameProperty);
}
public set userName(newName: string) {
this._setValue(TestView.userNameProperty, newName);
}
constructor() {
super();
var counter: number = 0;
var lbl = new label.Label();
var btn = new button.Button();
btn.text = "Tap me " + this.userName + "!";
btn.on(button.Button.tapEvent, (args: observable.EventData) => {
lbl.text = "Tap " + counter++;
});
this.addChild(lbl);
this.addChild(btn);
}
}
Use it in Angular template:
<StackLayout class="p-20">
<TestView userName="Felix"></TestView>
</StackLayout>
The component displays, but the button text does not show "Tap me [userName]", because userName is undefined.
What is the correct way to pass arguments as attributes for the component?
Update
Having read Data Binding and Properties, i augmented above code sample with definition of a userName property. But its still not set, quite frustrating...
Can anybody give some insight? Many thanks.
Finally got it working.
There has to be established Data Binding between
Angular template and custom Component TestView by encapsulating the property userName in a Property type of the ui/core/dependency-observable module (see above code).
the component and it's button by binding the component's userName source property to the button target text property (you can also set this by a default BindingContext).
var btn = new button.Button();
var buttonBindingOptions = {
expression: "'Tap me ' + userName + '!'",
sourceProperty: "userName",
targetProperty: "text",
twoWay: false
};
btn.bind(buttonBindingOptions, this);
In the parent Appcomponent user can by dynamically set like this:
app.component.ts:
export class AppComponent {
user : string;
constructor() {
this.user = "Felix";
setTimeout(()=> {this.user = "Other"}, 1000);
}
}
app.html:
<TestView [userName]="user"></TestView>