Make a NativeScript ListView Transparent on iOS - nativescript

I’m trying to get a NativeScript <ListView> to be transparent on iOS and I’m failing. I found an old thread on the topic at https://groups.google.com/forum/#!topic/nativescript/-MIWcQo-l6k, but when I try the solution it doesn’t work for me. Here’s my complete code:
/* app.css */
Page { background-color: black; }
<!-- main-page.xml -->
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="loaded">
<ListView id="list-view" items="{{ items }}" itemLoading="itemLoading">
<ListView.itemTemplate>
<Label text="{{ name }}" />
</ListView.itemTemplate>
</ListView>
</Page>
// main-page.js
var ios = require("utils/utils");
var Observable = require("data/observable").Observable;
var ObservableArray = require("data/observable-array").ObservableArray;
var page;
var items = new ObservableArray([]);
var pageData = new Observable();
exports.loaded = function(args) {
page = args.object;
page.bindingContext = pageData;
// Toss a few numbers in the list for testing
items.push({ name: "1" });
items.push({ name: "2" });
items.push({ name: "3" });
pageData.set("items", items);
};
exports.itemLoading = function(args) {
var cell = args.ios;
if (cell) {
// Use ios.getter for iOS 9/10 API compatibility
cell.backgroundColor = ios.getter(UIColor.clearColor);
}
}
Any help would be appreciated. Thanks!

Don't forget to set the listview to transparent, seems to have a backgroundcolor itself
ListView{
background-color: transparent;
}

Currently with NativeScript 2.4 the following works
var cell = args.ios;
if (cell) {
cell.selectionStyle = UITableViewCellSelectionStyleNone
}
And if you want to change the selection highlight color here is a simple approach, I have not tested performance but it works okay on an iPhone 6.
import { Color } from 'color';
cell.selectedBackgroundView = UIView.alloc().initWithFrame(CGRectMake(0, 0, 0, 0));
let blue = new Color('#3489db');
cell.selectedBackgroundView.backgroundColor = blue.ios

Not sure if there are better ways to do this, but this is what worked for me with NativeScript 2.4 on iOS to both A) make the ListView background transparent, and B) change the color when an item is tapped:
let lvItemLoading = (args) => {
let cell = args.ios;
if (cell) {
// Make the iOS listview background transparent
cell.backgroundColor = ios.getter(cell, UIColor.clearColor);
// Create new background view for selected state
let bgSelectedView = UIView.alloc().init();
bgSelectedView.backgroundColor = new Color("#777777").ios;
bgSelectedView.layer.masksToBounds = true;
cell.selectedBackgroundView = bgSelectedView;
}
};

Related

Nativescript-Vue Issue with Panning Elements around

So I am building a photo group creator in Nativescript-vue. I have the pan working and the view is rendering correctly. But my issue is when a user starts to pan the image outside the container it's in, the image goes 'behind' the container. And I need it to render ontop of everything. I have tried 'z-index' with css and still no go.
The idea is, there is a group of photos (un-grouped group). And the user will be able to click-and-drag a photo in the group down to an 'empty' group. And this in turn would create a new group. Or if there were other groups the user would be able to drag an image and add it to an existing group.
Any help or suggestions, thank you in advance!
This is my Vue Component
<template>
<StackLayout orientation="vertical" ref="mainContainer">
</StackLayout>
</template>
<script>
import * as StackLayout from 'tns-core-modules/ui/layouts/stack-layout';
import * as Image from 'tns-core-modules/ui/image';
import _ from 'underscore';
export default {
name: "photo-groupings",
props:{
photoList:{
type: Object,
required: true
}
},
mounted(){
let ungrouped = this.createGroupElement();
let newGroupElement = this.createGroupElement();
console.log(_.keys(this.photoList));
for(let pht of _.keys(this.photoList)){
console.log(pht);
console.log(this.photoList[pht]);
ungrouped.addChild(this.createImageChild(this.photoList[pht]))
}
this.$refs.mainContainer.nativeView.addChild(ungrouped);
this.$refs.mainContainer.nativeView.addChild(newGroupElement)
},
data(){
return {
photoGroups:{},
groupElements:{},
prevDeltaX: 0,
prevDeltaY: 0
}
},
methods:{
createImageChild(src){
let tempImg = new Image.Image();
tempImg.src = src;
tempImg.width = 100;
tempImg.height = 100;
tempImg.stretch = "aspectFill";
tempImg.borderRadius = 10;
tempImg.borderWidth = 2;
tempImg.borderColor = "forestgreen";
tempImg.margin = 5;
tempImg.on('pan', this.handlePan);
return tempImg;
},
createGroupElement(){
let tempGroup = new StackLayout.StackLayout();
tempGroup.orientation = "horizontal";
tempGroup.margin = 5;
tempGroup.borderColor = "black";
tempGroup.borderRadius = 5;
tempGroup.borderWidth = 1;
tempGroup.minHeight = 110;
return tempGroup;
},
handlePan(args){
if (args.state === 1) // down
{
this.prevDeltaX = 0;
this.prevDeltaY = 0;
console.log(args.view.getLocationRelativeTo(args.view.parent));
console.log(args.view.parent.getLocationInWindow());
}
else if (args.state === 2) // panning
{
args.view.translateX += args.deltaX - this.prevDeltaX;
args.view.translateY += args.deltaY - this.prevDeltaY;
this.prevDeltaX = args.deltaX;
this.prevDeltaY = args.deltaY;
}
else if (args.state === 3) // up
{
console.log("Pan release")
}
}
}
}
</script>
<style scoped>
</style>
Example Image of the images rendering 'behind'
The best way here would be creating a ghost element.
You should not move the original image but hide the original image when you detect drag, create a ghost of original image and insert it on the parent layout. When user drops the ghost image, destroy the ghost and move original image to destination.

how to add wrap Layout in scroll view dynamically

i want to add wrap layout elements in scroll view dynamically using java script.
but when i try to add scroll view child it says, it is not a function.
i want to know is it possible to achieve this or not.
one more thing is that i need to add layout by id i.e wrapId in below code.
<Page xmlns="http://www.nativescript.org/tns.xsd" navigatingTo="onNavigatingTo">
<Page.actionBar>
<ActionBar title="Wrap Layout" />
</Page.actionBar>
<ScrollView>
<StackLayout id="wrapId">
</StackLayout>
</ScrollView>
</Page>
this is my xml and below is the js
const WrapLayout = require("tns-core-modules/ui/layouts/wrap-layout").WrapLayout;
const StackLayout = require("tns-core-modules/ui/layouts/stack-layout").StackLayout;
var ScrollView = require('ui/scroll-view').ScrollView;
const Button = require("tns-core-modules/ui/button/").Button;
exports.onNavigatingTo = function (args) {
const page = args.object;
var wrapId = page.getViewById("wrapId");
const myWrap = new WrapLayout();
const myScroll = new ScrollView();
myScroll.orientation = "vertical";
for (let i = 0; i < 30; i++) {
var button = `button${i}`;
button = new Button();
button.backgroundColor = "#0099CC";
button.text = `${i}`;
button.width = 150;
button.height = 100;
button.margin = 4;
myWrap.addChild(button);
}
// myScroll.addChild(myWrap);
page.content = myWrap;
};
ScrollView is just like Page, inherited from ContentView which supports holding only one child element. So it should be,
myScroll.content = myWrap;

Nativescript RadListView: How to change background color programmatically on selected item?

Doing this programmatically in the code behind (not binding to XML), everything works except my background color does not show when the item is selected. No errors and my images show up fine. What's messed up in my code? (Thanks!)
I'm running {N} CLI "tns-android":"version": "3.4.2", "nativescript-ui-listview": "3.5.1".
<GridLayout columns="auto, *">
<StackLayout col="0" id="containers">
</StackLayout>
<StackLayout col="1" id="notes">
</StackLayout>
</GridLayout>
function setContainers() {
myCntnrPics.forEach(function (element) { // Need to it in ObservableArray
pathToCntnrBitmapsArray.push(element);
});
let radListLeft = new listview.RadListView();
// iOS NEEDS height set
radListLeft.height = 2000;
radListLeft.items = pathToCntnrBitmapsArray;
let gridLayout = new listview.ListViewGridLayout();
gridLayout.scrollDirection = "Vertical";
radListLeft.selectionBehavior = "Press";
radListLeft.itemSelected = "selected";
radListLeft.on("itemSelected", function (ListViewEventData) {
const item = pathToCntnrBitmapsArray.getItem(args.index);
item.selected = true;
console.log("itemSelected is true -----"); // This does not show up
});
radListLeft.on("itemTap", function (element){
var selectedItemPath = pathToCntnrBitmapsArray.getItem(element.index).toString();
console.log("on itemTap selectedItemPath: " + selectedItemPath); // shows correctly
});
if (application.android) {
// Android needs H & W
radListLeft.itemTemplate = "<StackLayout backgroundColor='{{ selected ? 'red' : 'white'}}'><Image src='{{ $value }}' height='123' width='123' loadMode='async' class='items'/></StackLayout>";
} else if (application.ios) {
radListLeft.itemTemplate = "<StackLayout backgroundColor='{{ selected ? 'red' : 'white'}}'><Image src='{{ $value }}' class='items'/></StackLayout>";
gridLayout.itemHeight = 123;
gridLayout.itemWidth = 123;
}
gridLayout.spanCount = 1;
radListLeft.listViewLayout = gridLayout;
let myContainers = page.getViewById("containers");
myContainers.removeChildren();
myContainers.addChild(radListLeft);
}

Xamarin Forms - Change View's location in a Grid

I have a grid on my page with a few items.
I want to change the location/span of these items in C#.
On Xaml I can do this:
<Grid>
<Label Grid.Row="1" Grid.RowSpan="2"/>
</Grid>
I could do grd.Children.Remove and then grd.Children.Add in the new position, but is there another way?
public MyPage()
{
var grid = new Grid();
var lbl1 = new Label { Text= "lbl1" };
var lbl2 = new Label { Text = "lbl2" };
grid.Children.Add(lbl1);
grid.Children.Add(lbl2);
Grid.SetRow(lbl1, 1);
Grid.SetRow(lbl2, 0);
this.Content = grid;
}
However I would recommend not to do it dynamically but once in the constructor. More info in the official doc.

How to add a visual prefix to an entry in Xamarin Forms?

Say I want to add a number prefix based on a country, for a phone entry? Like the one on the image:
How can I achieve that?
I would do something like this
<StackLayout Orientation="Horizontal" BackgroundColor="Gray">
<Label Text="+995 |" BackgroundColor="Transparent" />
<Editor Text="699999999" BackgroundColor="Transparent"></Editor>
</StackLayout>
A Horizontal stacklayout with a label for the prefix and an editor for the entry.
As you can see yourself i am using the same approach for my app in order to display the arrow down icon next to the picker.
var datectrl = new NoBorderPicker()
{
VerticalOptions = LayoutOptions.Center,
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)) * FontSizes.EditFormControlFactor,
HeightRequest = 40,
BackgroundColor = Color.White,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
var icon = new IconView()
{
Source = "ic_keyboard_arrow_right_black_24dp",
Foreground = Palette._019,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.End,
Margin = new Thickness(0, 0, 5, 0)
};
var stack = new StackLayout()
{
Orientation = StackOrientation.Horizontal,
Children =
{
datectrl,
icon
}
};
The NoBorderPicker is a custom renderer in order to remove the border for the picker control
[assembly: ExportRenderer(typeof(NoBorderPicker), typeof(CustomPicker))]
namespace ThesisSFA.Droid.Renderers
{
public class CustomPicker : PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var customBG = new GradientDrawable();
customBG.SetColor(Android.Graphics.Color.Transparent);
customBG.SetCornerRadius(3);
Control.SetBackground(customBG);
var custdatepicker = (NoBorderPicker) this.Element;
this.Control.TextSize = (float)custdatepicker.FontSize;
}
}
}
}
You can just use masking behavior.
<Entry.Behaviors>
<behavior:MaskedBehavior Mask="(995) XX-XXX-XXXX" />
</Entry.Behaviors>
enter code here
and to add behavior just use the following link.
https://xamarinhelp.com/masked-entry-in-xamarin-forms/

Resources