How to create screen size independent UI in Titanium alloy - titanium-mobile

Created layout after setting the height and width of child elements based on current device screen width and height,as you can see the code snippet which calculates the width and height based on screen size for each child element.
How to do the same or similar settings using Xml mark up to create view in alloy project if not using '%',or 'dp'
function Cal_width(size) {
var width;
try {
width = size * Titanium.Platform.displayCaps.platformWidth / 100;
} catch(e) {
warn("Error accessing display caps for screen density calculation: " + e);
}
return width;
}
function Cal_height(size) {
var height;
try {
height = size * Titanium.Platform.displayCaps.platformHeight / 100;
} catch(e) {
warn("Error accessing display caps for screen density calculation: " + e);
}
return height;
}
const topOffset = Cal_height(1);
const topOffset_label = Cal_height(5);
//const leftOffsetLabel = Cal_width(30);
const leftOffset = Cal_width(5);
const rightOffset = Cal_width(5);
const textFieldHeight = Cal_height(8);
const textFieldWidth = Cal_width(90);
const txtFieldEmailTopOffset = Cal_height(5);
const btnLogin_width = Cal_width(90);
const btnHeight = Cal_height(10);
const topOffsetCreateBtn = Cal_height(6);
const btnCreate_Width = Cal_width(100);
const font_Size = Cal_height(3);
const logo_height = Cal_height(10);
const logo_width = Cal_width(80);
const logoTopOffSet = Cal_height(5);
const leftForgotPswd = Cal_width(40);
// specify visual assets' heights
var win = Titanium.UI.createView({
layout : 'vertical'
});
var applogo = Titanium.UI.createLabel({
width : logo_width,
top : logoTopOffSet,
height : logo_height,
backgroundImage : 'android/_logo.png'
});
win.add(applogo);
//create label to show error in email textfield
var lbemail_error = Titanium.UI.createLabel({
top : topOffset_label,
color : 'red',
textAlign:'center',
font : {
fontFamily : 'Arial',
fontSize : Cal_height(3)
}
});
win.add(lbemail_error);
//create textfield for email input and set its position with respect the screen
var tfemailInput = Titanium.UI.createTextField({
top : Cal_height(5),
left : leftOffset,
right : rightOffset,
width : textFieldWidth,
height : textFieldHeight,
hintText : 'Email',
keyboardType : Titanium.UI.KEYBOARD_EMAIL,
returnKeyType : Titanium.UI.RETURNKEY_NEXT,
borderStyle : Titanium.UI.INPUT_BORDERSTYLE_ROUNDED,
font : {
fontFamily : 'Arial',
fontSize : font_Size
}
});
win.add(tfemailInput);

In alloy you'd ideally use tss files for styling instead of throwing everything into XML attributes. Alloy's tss files can access variables in Alloy.CFG, which you can define. So you can do something like this:
alloy.js
Alloy.CFG.Cal_width = function (size) { /* your code here*/ };
Alloy.CFG.Cal_height = function (size) { /* your code here*/ };
Alloy.CFG.topOffset_label = Alloy.CFG.Cal_height(5)
screen.xml
<Label id="lbemail_error"></Label>
screen.tss
"#lbemail_error": {
top : Alloy.CFG.topOffset_label,
color : 'red',
textAlign:'center',
font : {
fontFamily : 'Arial',
fontSize : Alloy.CFG.Cal_height(3)
}
}

Related

Set a NativeScript Label line height on iOS

I have a label with a large font size, and the default line-height is quite loose for my taste. I'd like to reduce it to less than the default.
Providing a line-height value larger than the font-size does increase the line spacing, but a smaller value (or negative value) does not reduce it to be smaller than the default on iOS.
From a GitHub issue, I got this snippet that I updated to work with the latest NS;
import { Label } from "#nativescript/core/ui/label";
export function setIOSLineHeight(label: Label, lineHeight: number){
const iosLabel = label.nativeView;
let attributedString;
if (iosLabel.attributedText) {
attributedString = iosLabel.attributedText;
} else {
attributedString = NSMutableAttributedString.alloc().initWithString(iosLabel.text);
}
let range = new NSRange({ location: 0, length: iosLabel.text.length });
const paragraphStyle = NSMutableParagraphStyle.alloc().init();
paragraphStyle.lineSpacing = 0;
paragraphStyle.minimumLineHeight = lineHeight;
paragraphStyle.maximumLineHeight = lineHeight;
attributedString.addAttributeValueRange(NSParagraphStyleAttributeName, paragraphStyle, range);
iosLabel.attributedText = attributedString;
}
However, calling this method in the mounted() lifecycle method does not have any effect for any value of lineHeight - even ones that do have an effect via the CSS property:
<template>
<Page ref="page">
<Label ref="topLine" text="Hello this is a text that flows onto multiple lines" textWrap="true" />
</Page>
</template>
<script>
import { isIOS } from 'tns-core-modules/platform';
import { setIOSLineHeight } from '../label-helper.ts';
export default {
mounted() {
if (isIOS) {
/* Has no effect, regardless of value */
setIOSLineHeight(this.$refs.topLine, 40);
}
}
}
</script>
<style lang="scss" scoped>
Label {
font-size: 60;
/* Does work */
line-height: 100;
/* Does not work */
line-height: 40;
}
</style>
How can I reduce the line height of my Label to a value smaller than the font size?
In NativeScript I have used the following code to handle both IOS and Android for Line Spacing
function labelLineHeight(nsLabel) {
if(isIOS){
var label= nsLabel.ios;
var attributedString;
if(label.atributedText){
attributedString = label.atributedText;
}
else{
attributedString=NSMutableAttributedString.alloc().initWithString(label.text);
}
var paragraphStyle = NSMutableParagraphStyle.alloc().init();
paragraphStyle.lineSpacing = 5;
var range= NSMakeRange(0, label.text.length);
attributedString.addAttributeValueRange(NSParagraphStyleAttributeName, paragraphStyle, range);
label.attributedText = attributedString;
}
if(isAndroid){
var label = nsLabel.android;
//Default spacing is 20% of text size
//setLineSpacing(add,multiplyby);
label.setLineSpacing(12, 1);
}
}
Also follow this thread for more inputs on the line-spacing. You can see the pull request too for reference.

How to adjust width and spacing of MicroCharts-Barchart in xamarin forms

I am using MicroCharts-Barchart to implement charts in Xamarin forms application. I want to set width of the bar and also spacing between bars, but I could not find any property to set this
Below is the code snippet I am using
Xaml
<forms:ChartView x:Name="Chart4"
HeightRequest="400"
/>
.cs file code
public partial class ChartsPage : ContentPage
{
List<Entry> entries = new List<Entry>
{
new Microcharts.Entry(200)
{
Color=SKColor.Parse("#FF1943"),
Label ="January",
ValueLabel = "200",
},
new Entry(400)
{
Color = SKColor.Parse("00BFFF"),
Label = "March",
ValueLabel = "400"
},
new Entry(-100)
{
Color = SKColor.Parse("#00CED1"),
Label = "Octobar",
ValueLabel = "-100"
},
};
public ChartsPage()
{
InitializeComponent();
Chart4.Chart = new BarChart() { Entries = entries };
}
}
And it shows like below
If MicroCharts does not have this feature, please suggest if there is any other library which has this feature.
XAML:
You need to set the HorizontalOptions as StartAndExpand as follows:
<forms:ChartView x:Name="Chart4" HeightRequest="400" HorizontalOptions="StartAndExpand"/>
.cs File Code:
You need to set the Width of the Chart = NumberOfBars X BarWidth as follows:
public ChartsPage()
{
InitializeComponent();
Chart4.Chart = new BarChart() { Entries = entries };
//Set the WidthRequest of your Chart based on the following calculation.
//Here, barWidth will be the width of the Bar in your Chart
int barWidth = 50;
Chart4.WidthRequest = entries.Count * barWidth;
}
To set the spacing between bars, use Margin as follows:
Chart4.Chart = new BarChart() { Entries = entries, Margin = 20 };
Hope this will help you.

How to stop event bubbling in kendo color picker widget?

I'm in developing custom Map View component with kendo-colorpicker(kendoFlatColorPicker) to change color of markers.
the root element of flatcolorpicker is child element of map view wrapper element.
<div id="map-view">
<!--some elements....-->
<div id="custom-flat-color-picker"></div>
</div>
In kendoFlatColorPicker, user can select color in hsvRect panel by dragging mouse.
There is a critical issue...
When Pressing mouse button and dragging mouse on FlatColorPicker panel, the map image in Map View is also dragged.
I think that this issue came from event-bubbling. So, I try to use e.stopPropagation() method in 'mousedown' event.
However, it is not working.
Other ways, I also try to customize _hsvEvets method in kendo FlatColorPicker source code through widget extends like below code.
var KEYDOWN_NS = 'keydown.kendoEditor';
var bind = kendo.bind;
var FlatColorPicker = kendo.ui.FlatColorPicker;
var extendFlatColorPicker = FlatColorPicker.extend({
options: {
name: 'CustomFlatColorPicker'
},
init: function (element, options){
var self = this;
FlatColorPicker.fn.init.call(self, element, options);
},
_hsvArea: function () {
var that = this,
element = that.element,
hsvRect = element.find('.k-hsv-rectangle'),
hsvHandle = hsvRect.find('.k-draghandle').attr('tabIndex', 0);
function update(x, y) {
var offset = this.offset, dx = x - offset.left, dy = y - offset.top, rw = this.width, rh = this.height;
dx = dx < 0 ? 0 : dx > rw ? rw : dx;
dy = dy < 0 ? 0 : dy > rh ? rh : dy;
that._svChange(dx / rw, 1 - dy / rh);
}
that._hsvEvents = new kendo.UserEvents(hsvRect, {
global: true,
press: function (e) {
//this.element.get(0).dispatchEvent(new Event('mousedown'));
this.offset = kendo.getOffset(hsvRect);
this.width = hsvRect.width();
this.height = hsvRect.height();
hsvHandle.focus();
update.call(this, e.x.location, e.y.location);
},
start: function () {
hsvRect.addClass('k-dragging');
hsvHandle.focus();
},
move: function (e) {
e.preventDefault();
update.call(this, e.x.location, e.y.location);
},
end: function () {
hsvRect.removeClass('k-dragging');
}
});
that._hsvRect = hsvRect;
that._hsvHandle = hsvHandle;
// var cb = that._hsvEvents.press;
// that._hsvEvents.press = function(e){
// e.stopPropagation();
// cb.call(this);
// };
}
});
kendo.ui.plugin(extendFlatColorPicker);
When user press mouse button to drag mouse, 'press' event is occured on flat color picker, however parameter 'e' has no method stopPropagation().
How can I stop bubbling from colorpicker to map view?
I solved this issue.
I found event 'pointerdown' in event listener stack that can be found in chrome dev tool. About this event, I applied e.stopPropagation().

I want change scrollview rolling speed in react native

Now I use interval make it come true, but it is very incoherence.
If I can just change the method (scroll) speed, it well be nice.
this.interval = setInterval(()=>{
if(!_scroll){
_this.interval && clearInterval(_this.interval);
}
if(totalWide+ScreenWidth >= width ){
_scroll.scrollWithoutAnimationTo();
totalWide=0;
i=0;
}else{
_scroll.scrollTo({x:eachWide*i,animate:true});
totalWide = totalWide + eachWide;
i= i+1;
}
},250)
use decelerationRate property of ScrollView
<ScrollView decelerationRate={0.5}>
</ScrollView>
I got this working by having setInterval call a function(in which you define the logic or the pace at which the scroll should move).
this.interval= setInterval(this.scrollwithSpeed, 100); // Set the function to this timer
scrollwithSpeed() {
position = this.state.currentPosition + x; // x decides the speed and
currentPosition is set to 0 initially.
this.scrollObject.scrollTo(
{ y: position, animated: true }
);
this.setState({ currentPosition: position });
}
Make sure you call clearInterval(this.interval) after it is done.
I would suggest to attach to js requestAnimationFrame (from how far I know it is supported in React Native).
Bellow example will scroll linearly from top to bottom. If You need to scoll to different offset just change distance variable.
startingPoint variable is redundant in scrolling from top to bottom but will stay in example.
scroll() {
if (this.scrollAnimationFrame) {
cancelAnimationFrame(this.scrollAnimationFrame);
}
this.listRef.scrollToOffset({offset: 0, animated: false}); // remove if You don't start scroll from top
const duration = this.scrollTime,
startingPoint = 0, // change if You don't start scroll from top
distance = Scrolling.LINE_HEIGHT * Scrolling.ITEMS_COUNT;
let startTimestamp, progress;
const frameCallback = (timestamp) => {
if (!startTimestamp) {
startTimestamp = timestamp;
}
progress = timestamp - startTimestamp;
this.listRef.scrollToOffset({
offset: distance * (progress / duration) + startingPoint,
animated: false,
});
if (progress < duration) {
this.scrollAnimationFrame = requestAnimationFrame(frameCallback);
}
};
this.scrollAnimationFrame = requestAnimationFrame(frameCallback);
}
You can use reanimated to make it work.
const offsetY = useSharedValue(0);
const animatedProps = useAnimatedProps<FlatListProps<unknown>>(() => {
return {
contentOffset: {
x: 0,
y: offsetY.value,
},
};
});
const handleScroll = () => {
offsetY.value = withTiming(targetIndex * CARD_HEIGHT, {
duration: YOUR_DURATION_HERE,
});
}
return <Animated.FlatList animatedProps={animatedProps} ... />

QML changing size of image

I have an image object in QML (QtQuick 1.0), its height must be relative (in case of window scaling), but the problem is when I try to display this image in fullsize. Please look at the following part of my code:
Image {
id: selectionDialogImage
source: "qrc:/Images/myImage.png"
property int oldHeight: sourceSize.height
sourceSize.height: testsList.height/3
scale: 1
anchors.bottom: parent.bottom
anchors.left: parent.left
visible: false
property bool imageFullsize: false
MouseArea {
anchors.fill: parent
onClicked:
{
if(parent.imageFullsize)
{
parent.parent = selectionDialogQuestionText;
parent.sourceSize.width = undefined;
parent.sourceSize.height = testsList.height/3;
parent.anchors.horizontalCenter = undefined;
parent.anchors.verticalCenter = undefined;
parent.anchors.left = selectionDialogQuestionText.left;
parent.anchors.bottom = selectionDialogQuestionText.bottom;
parent.imageFullsize = false;
}
else
{
parent.parent = mainItem;
parent.sourceSize.height = parent.oldHeight;
//parent.sourceSize.height = undefined;
parent.sourceSize.width = mainItem.width;
parent.anchors.horizontalCenter = mainItem.horizontalCenter;
parent.imageFullsize = true;
}
}
}
}
selectionDialogQuestionText is a default parent of my image item. mainItem is the largest item, it has size of the whole window. So I want to have the image size set on the basis of width when I'm displaying it on a fullscreen, but in another state I want to scale the image setting its height.
When I set parent.sourceSize.width = mainItem.width;, image isn't scaled, but its height is as previous (very little) so its proportions are inappropriate.
Can I store old height of source image in any way? I need something like const, because property int oldHeight: sourceSize.heigh is relative. Or is there a way to restore default size of image and then set height/width?
UPDATE #1:
I tried to use method described by #Mitch:
property int oldHeight
Component.onCompleted: {
oldHeight = sourceSize.height
}
sourceSize.height: 250
but console.log("oldHeight="+parent.oldHeight) a few lines below shows oldHeight=250, not original height.
Can I store old height of source image in any way?
You can use Component.onCompleted:
Image {
// ...
Component.onCompleted: {
oldHeight = sourceSize.height
}
}

Resources