I'm using the NativeScript StackLayout component to layout my elements.
What is the best approach to create a gap between the child elements of a StackLayout?
You can use margin in the css for that layout.
In you XML:
<StackLayout>
<Label text="Hey there,"></Label>
<Label text="world!"></Label>
</StackLayout>
In your css:
StackLayout Label {
margin: 10;
}
Related
I try out and build my first App on Svelte Native. I develop this for an Tablet.
The standard ListView only supports vertical stacking.
I need this for horizontal.
This part only works for vertical:
<listView items="{listOfItems}" on:itemTap="{onItemTap}">
<Template let:item>
<!-- Shows the list item label in the default color and style. -->
<label text="{item}" />
</Template>
</listView>
<script>
import { Template } from 'svelte-native/components'
let listOfItems = ['one', 'two', 'three']
</script>
I also try this:
Here i have the Problem that nothing is showing.
{#each one as ones}
<button on:tap={addToList(ones)} text="{ones.name}" class="prod-btn" />
{/each}
So i need help to show a list of objects in an horizontal view.
I have this sample code that works as I want:
<ScrollView orientation="horizontal">
<GridLayout columns="*,*,*,*,*,*" >
<Label class="gridlabel" col="0" text="Monday" />
<Label class="gridlabel" col="1" text="Tuesday" />
<Label class="gridlabel" col="2" text="Wednesday" />
<Label class="gridlabel" col="3" text="Thursday" />
<Label class="gridlabel" col="4" text="Friday" />
<Label class="gridlabel" col="5" text="Saturday" />
</GridLayout>
</ScrollView>
That is, the labels within the GridLayout scroll horizontally.
I have a component that generates a GridLayout, and now I need to wrap that in a horizontal ScrollView.
That is, I for each label:
let label = new Label();
// Add tap event handler for each tab
label.on("tap", function () {
onTabTap(label, "tabTap");
}.bind(label));
label.id = key;
label.text = key;
label.class = "gridtab";
this.addColumn(new ItemSpec(1, GridUnitType.STAR));
GridLayout.setColumn(label, i);
GridLayout.setRow(label, 0);
this.addChild(label);
But when I try to add the ScrollView, I get errors. If I try to add the labels to the ScrollView, such as scrollView.addChild(label) (where scrollView is an instance of ScrollView), I get "scrollView.addChild is not a function". (See this similar SO post). If, as suggested in the mentioned post, I use scrollView.content = this; then I get the error, Error: View already has a parent.
So, the question is, from code, how do I replicate the hierarchy from my sample xml? That is, how can I wrap the generated GridLayout in a horizontal ScrollView?
Edit 7/17/2020
Upon reflection, I don't think this can work given my component's current design. That is, it subclasses GridLayout, and I want the generated GridLayout to be wrapped by a ScrollView, but that would be external to the content generated by the component, yes? It almost seems I'd need to subclasss ScrollView, and then generate the GridLayout within.
So, I was ultimately able to resolve this by subclassing StackLayout, then within the StackLayout adding a ScrollView, and within the ScrollView adding the GridLayout. The "magic" is:
scroll.content = grid;
this.addChild(scroll);
Where scroll is the ScrollView instance, and grid is the GridLayout instance.
Then, after spending a day on this I found I didn't actually need horizontal scrolling after all, but at least I know what to do should the need arise.
I have the following hack that draws drop shadows for the various elements that I have:
<template>
<Page>
<TabView>
<TabViewItem title="Tab 1">
<StackLayout #loaded="addShadow">
<Label text="This box does have a shadow." />
</StackLayout>
</TabViewItem>
<TabViewItem title="Tab 2">
<StackLayout>
<Label text="This box doesn't have a shadow." />
</StackLayout>
</TabViewItem>
</TabView>
</Page>
</template>
<script>
export default {
methods: {
addShadow(event) {
if (event.object.ios) {
event.object.ios.layer.masksToBounds = false;
event.object.ios.layer.shadowOpacity = 0.5;
event.object.ios.layer.shadowRadius = 5.0;
event.object.ios.layer.shadowColor = new Color('#000000').ios.CGColor;
event.object.ios.layer.shadowOffset = CGSizeMake(0.0, 2.0);
}
}
}
}
</script>
<style scoped>
StackLayout {
background: #ffffff;
padding: 16;
margin: 16;
}
</style>
However, while the shadow looks perfect, it does not initially appear when the tab is first accessed. I have to first visit the second tab, and only after returning to the first tab, does the drop shadow get drawn.
I assume this is because I need to invoke something to redraw the layer after adding the shadow, but I cannot figure out how to do that. I've tried event.object.ios.layer.setNeedsDisplay() but it has no effect.
How can I ensure the shadow displays on the first tab render?
I have this simple layout markup :
<StackLayout orientation="horizontal" #myStack>
<StackLayout width="300" backgroundColor="red">
</StackLayout>
<StackLayout width="300" backgroundColor="green">
</StackLayout>
</StackLayout>
As you can see , both are same width of 300:
Let's see this :
Notice that green is also 300 but we only see a part of it since 300+300 > screen size.
Ok so let's try to animate #myStack (!!) to the left , in order to see the left green :
ngOnInit(): void {
setTimeout(() => {
this.myStack.nativeElement.animate({
translate: { x: -300, y: 0 },
duration: 2000,
curve: enums.AnimationCurve.easeIn
});
},1000)
}
Question:
What is this white area on the right ? there should be also a green section there
Basically this is the situation :
So i'm expecting the green from the right to be scrolled to the left , i'm basically trying to move #myStack left.
How can I make the green area slide from the right ?
PLAYGROUND
Copy/paste this answer so that the community can see the provided solutions:
#RoyiNamir this is expected behavior.
What is happening is that by default the root layout will have an effective width (and height) as the screen size.
You need to explicitly create the wider container if you want to have an effective width larger than the screen width.
There are several approaches on how to achieve that.
- use container with fixed width - demo Playground here
<GridLayout rows="auto, *" columns="600" backgroundColor="lightgray">
<Button row="0" text="animate" (tap)="animate()"></Button>
<StackLayout row="1" orientation="horizontal" #myStack>
<StackLayout width="300" backgroundColor="red">
<Label text="Label"></Label>
</StackLayout>
<StackLayout width="300" backgroundColor="green">
<Label text="Label"></Label>
</StackLayout>
</StackLayout>
</GridLayout>
Note that our container GridLayout has columns set to 600.
Another option is instead of creating fixed size container to use ScrollView (which will measure its children so the children should have predefined size - in your case width="300") - demo Playground here
In the example above the container element is not needed (used just to create the animate Button).
The ScrollView will measure its children (300 + 300 = 600 width) and will take the space needed.
I am trying to create a border-radius and border-color around a StackLayout but for some reason the styles doesn't get applied... I am using the Nativescript core-light theme, not sure if that can override my inline styles? Any idea what i'm doing wrong?
my code:
<StackLayout borderRadius="5px" borderColor="blue">
<Label class="body" [text]="'Description: ' + product.Description"></Label>
<Label class="body" [text]="'POS Description: ' + product.POSDescription"></Label>
<Label class="body" [text]="'POS price: R' + product.POSPrice"></Label>
<Label class="body" [text]="'Stock On Hand: ' + product.StockOnHand"></Label>
</StackLayout>
You need to set explicitly borderWidth and your code will work.
e.g.
<StackLayout borderRadius borderWidth="2" borderRadius="15" borderColor="blue">
Notice that I am using DPs (device independent pixels) instead of px which in the mobile world with different screen densities and resolutions should be the better approach.
You can also use CSS for your borders
e.g.
.borders {
border-width: 2;
border-color: red;
border-radius: 20;
}