Xamarin.Forms Relative layout strange behavior - xaml

I face problem with relative layout.
My target is to create similar layout:
Disclaimer: This should be relative layout just because i need add some other elements which position depends on this two.
This is my code:
var layout = new RelativeLayout();
var box = new BoxView { BackgroundColor = Color.Olive, WidthRequest = 50, HeightRequest = 50 };
var label = new Label
{
LineBreakMode = LineBreakMode.WordWrap,
Text = "Here is a lot of text ..... Here is a lot of text";
};
layout.Children.Add(box, Constraint.Constant(10), Constraint.Constant(10));
layout.Children.Add(label,
Constraint.RelativeToView(box, (relativeLayout, view) => view.X + view.Width + 20),
Constraint.RelativeToView(box, (relativeLayout, view) => view.Y),
//Constraint.RelativeToParent(relativeLayout => relativeLayout.Width - 20 - 50 -10));
MainPage = new ContentPage
{
Content = layout
};
Here is my problem. If I not add commented line then label is out of the screen.
Like here:
If I add commented string (which is width constraint) then there is another strange thing: Text is not fully displayed. I mean that there should be ~10 more words but they suddenly disappear.
I don't set any Height constraints so it should not limit the size of label.
Could you please help me with this?
Thank you!

Be sure you're setting RelativeLayout HorizontalOptions and VerticalOptions to fill the screen
Calculate label X Constraint correctly view.X + view.Width + 20 -> view.X + view.Width + 10
The label height is incorrect because you didn't set it. When you use AbsoluteLayout or RelativeLayout you MUST set its children sizes manually. It's how it's designed.
Here is working example:
var layout = new RelativeLayout() {
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
const double boxSize = 50;
const double margin = 10;
var box = new BoxView {
BackgroundColor = Color.Olive,
WidthRequest = boxSize,
HeightRequest = boxSize
};
var label = new Label {
LineBreakMode = LineBreakMode.WordWrap,
Text = "Cras efficitur, sem a scelerisque pretium, leo turpis cursus lacus, id consequat erat risus sit amet tortor. Nullam fringilla vestibulum mauris, vel fringilla lectus molestie eget. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent quis elit eu nulla varius consectetur. Ut eleifend odio at malesuada lacinia. Fusce neque orci, efficitur nec condimentum et, volutpat id odio. Quisque vel metus vitae lectus vulputate placerat. Aliquam erat volutpat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec suscipit, ipsum nec tincidunt porta, enim lacus consequat magna, nec scelerisque lacus lacus luctus mi. Proin rutrum luctus libero, sed lacinia tellus. Nunc dapibus arcu dui, quis bibendum elit interdum sit amet. Vivamus sed consequat mi. Aliquam sagittis ante ac massa bibendum, eu pharetra diam malesuada. Duis maximus magna id lorem lacinia, sed consectetur quam sagittis. Fusce at pulvinar ex."
};
layout.Children.Add(box, Constraint.Constant(margin), Constraint.Constant(margin));
layout.Children.Add(label,
Constraint.RelativeToView(box, (relativeLayout, view) => view.X + boxSize + margin),
Constraint.RelativeToView(box, (relativeLayout, view) => view.Y),
Constraint.RelativeToParent((relativeLayout) => relativeLayout.Width - boxSize - margin * 3),
Constraint.RelativeToParent((relativeLayout) => relativeLayout.Height * 0.8f)); // eg. 80% of its parent

There is nothing stopping you leveraging the layout of a stack within your relative layout.
E.g.
var stackLayout = new StackLayout {
Orientation = StackOrientation.Horizontal,
Padding = new Thickness (20, 10, 10, 0),
Children = {
new BoxView {
BackgroundColor = Color.Olive,
WidthRequest = 50,
HeightRequest = 50,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Start
},
new Label {
LineBreakMode = LineBreakMode.WordWrap,
HorizontalOptions = LayoutOptions.FillAndExpand,
Text = "Here is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of textHere is a lot of text ..... Here is a lot of text"
}
}
};
var relLayout = new RelativeLayout ();
relLayout.Children.Add (stackLayout,
Constraint.Constant (0),
Constraint.Constant (0),
Constraint.RelativeToParent((p)=>{return p.Width;}),
Constraint.RelativeToParent((p)=>{return p.Height;})
);
Of course, you will need to tinker around with the values but the basic premise is there.

Related

How Print Vue Component W/ Styles

I'm trying to print a component using VueJS all style is in the same file, but it's not getting the CSS Styling. Also I use Quasar framework, don't know if it can affect the final result.
<div style="margin: 12px 12px">
<div class="central-layout">
<p>
<strong
><a href="https://www.nightprogrammer.com/" target="_blank"
>Nightprogrammer.com</a
></strong
>: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
posuere, tellus lobortis posuere tempor, elit sem varius libero, ac
vulputate ante orci vel odio. Nam sit amet tortor malesuada tellus
rutrum varius vel a mauris. Integer volutpat neque mauris, vel imperdiet
mi aliquet ac. Proin sed iaculis ipsum. Vivamus tincidunt egestas
sapien, vitae faucibus velit ultricies eget. Donec mattis ante arcu, a
pretium tortor scelerisque et. Morbi sed dui tempor, consectetur turpis
sed, tristique arcu.
</p>
</div>
</div>
<style scoped>
.central-layout{
flex-direction: column-reverse;
}
</style>
exportToPDF() {
const content = this.$refs.printInteraction.innerHTML
let cssHtml = ''
for (const node of [...document.querySelectorAll('style')]) {
cssHtml += node.outerHTML
}
const winPrint = window.open('', '', 'left=0,top=0,width=800,height=900,toolbar=0,scrollbars=0,status=0')
winPrint.document.write(`<!DOCTYPE html>
<html>
<head>
${cssHtml}
</head>
<body>
${content}
</body>
</html>`)
winPrint.document.close()
winPrint.focus()
winPrint.print()
winPrint.close()
}
}
}
Can anyone help me?
I need to print with the styling set in the page
Exporting that properly may be quite difficult because not all the things are properly supported. I recommend the usage of this: https://github.com/niklasvh/html2canvas
Then you could convert the image into a PDF. But anyway, such thing is quite heavy and should be handled by some backend: convert, host the file on AWS/alike and sent back as a callback.

How can I inject fonts and colour variables (fetched from backend api upon page load) into Nuxt.js styles?

I am building an application in Nuxt.js where each clients can configure custom fonts & colours depending on their brand. Clients can specify upto 3 fonts and 3 colours, which are exposed to the front-end via an api endpoint:
Fonts:
primary-font
secondary-font
tertiary-font
Colours:
primary-colour
seconday-colour
tertiary-colour
How can I inject these fonts and colours into the application when a user visits the clients link https://{client-slug}.{domain}.com ?
You can construct a FontFace object and inject it to the document.
Following are the example of how you can achieve it. You can run the code snippet:
const fontFamily = 'Sansita Swashed'; // your custom font family
const fontSrc = 'https://fonts.gstatic.com/s/sansitaswashed/v1/BXR8vFfZifTZgFlDDLgNkBydPKTt3pVCeYWqJnZSW7RpXTIfeymE.woff2' // your custom font source
function injectCustomFont() {
const customFont = new FontFace(fontFamily, `url(${fontSrc})`);
customFont.load().then((font) => {
document.fonts.add(font);
document.body.style.fontFamily = '"Sansita Swashedr", cursive';
});
}
document.getElementById('btnFontChanger').addEventListener('click', () => {
injectCustomFont();
});
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<button id="btnFontChanger" type="button">Click to change font</button>
FontFace() constructor can accept one more parameter. Learn more at here.
Note:
FontFace is still an experimental. You must double check the browser compatibility before using it.
Relatable links:
https://usefulangle.com/post/74/javascript-dynamic-font-loading
https://developer.mozilla.org/en-US/docs/Web/API/FontFace/FontFace

How to change the layout of ion-slide?

I'm trying to use ion-slides:
<ion-content>
<ion-slides pager="true" [options]="slideOpts">
<ion-slide class="step-one">
<h1>Welcome</h1>
<p>Lorem ipsum dolor sit amet, massa nam ante. Vel lacus viverra volutpat tortor ligula ornare, varius ut mauris ipsum mus torquent, scelerisque suspendisse penatibus, purus et arcu ipsum vehicula quam luctus. Consectetuer sed urna accumsan. Nec viverra felis varius pretium, volutpat in et cras, odio consectetuer lacinia risus feugiat sit etiam, commodo pulvinar, dolor non et inventore.</p>
</ion-slide>
<ion-slide class="step-two">
<h1>Heading</h1>
<p>blah, blah</p>
</ion-slide>
<ion-slide class="step-three">
<h1>Heading</h1>
<p>blah, blah</p>
<ion-button (click)="end()">END</ion-button>
</ion-slide>
</ion-slides>
</ion-content>
However, I was expecting the flow of content to be top-to-bottom rather than having the "Welcome" header to the left.
I've looked at the slider layout documentation but I couldn't see how to change the layout to flow vertically down the page.
By inspecting the css in the browser debugger, I figured out that I could change the flex model and by adding the following to my page.scss it appears to fix the problem. Is there a more 'ionic' way to solve this?
.swiper-slide {
flex-direction: column;
}
Apologies if this question is very basic, I'm a data specialist so front end development is not (yet) a strength of mine.
The solution for me was to add the following css:
.swiper-slide {
flex-direction: column;
}

Kivy ScrollView for paragraphs of text

I am unable to get ScrollView in Kivy to scroll through paragraphs of text. I have attached a code example below. Can anyone state what is wrong? Thank you.
import kivy
import string
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
class longTextLabelApp(App):
def build(self):
scrollViewLayout = ScrollView(do_scroll_x=False)
childLayout = GridLayout(cols = 1, size_hint_x = 1, size_hint_y = None)
childLayout.bind(minimum_height=childLayout.setter('height'))
def longTextLabel():
_long_text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus odio nisi, pellentesque molestie adipiscing vitae, aliquam at tellus. Fusce quis est ornare erat pulvinar elementum ut sed felis. Donec vel neque mauris. In sit amet nunc sit amet diam dapibus lacinia. In sodales placerat mauris, ut euismod augue laoreet at. Integer in neque non odio fermentum volutpat nec nec nulla. Donec et risus non mi viverra posuere. Phasellus cursus augue purus, eget volutpat leo. Phasellus sed dui vitae ipsum mattis facilisis vehicula eu justo.
Quisque neque dolor, egestas sed venenatis eget, porta id ipsum. Ut faucibus, massa vitae imperdiet rutrum, sem dolor rhoncus magna, non lacinia nulla risus non dui. Nulla sit amet risus orci. Nunc libero justo, interdum eu pulvinar vel, pulvinar et lectus. Phasellus sed luctus diam. Pellentesque non feugiat dolor. Cras at dolor velit, gravida congue velit. Aliquam erat volutpat. Nullam eu nunc dui, quis sagittis dolor. Ut nec dui eget odio pulvinar placerat. Pellentesque mi metus, tristique et placerat ac, pulvinar vel quam. Nam blandit magna a urna imperdiet molestie. Nullam ut nisi eget enim laoreet sodales sit amet a felis.
"""
reallyLongText = _long_text + _long_text + _long_text + _long_text +_long_text
myLabel = Label(text = reallyLongText, text_size = (700,None), line_height=1.5)
return myLabel
childLayout.add_widget(longTextLabel())
scrollViewLayout.add_widget(childLayout)
return scrollViewLayout
if __name__ == '__main__':
longTextLabelApp().run()
The default size of a Label (and Widget) is (100,100). It doesn't matter if you are seeing all the text on the screen. If you print myLabel.size you will realize of this. You need to be sure to set the height of the Label (myLabel.height: 2200) but first set the size_hint_y to None first (myLabel.size_hint_y=None). The following code should work:
import kivy
import string
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.scrollview import ScrollView
from kivy.graphics import Rectangle, Color
class longTextLabelApp(App):
def build(self):
scrollViewLayout = ScrollView(do_scroll_x=False)
childLayout = GridLayout(cols = 1, size_hint_x = 1, size_hint_y = None)
childLayout.bind(minimum_height=childLayout.setter('height'))
def longTextLabel():
_long_text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus odio nisi, pellentesque molestie adipiscing vitae, aliquam at tellus. Fusce quis est ornare erat pulvinar elementum ut sed felis. Donec vel neque mauris. In sit amet nunc sit amet diam dapibus lacinia. In sodales placerat mauris, ut euismod augue laoreet at. Integer in neque non odio fermentum volutpat nec nec nulla. Donec et risus non mi viverra posuere. Phasellus cursus augue purus, eget volutpat leo. Phasellus sed dui vitae ipsum mattis facilisis vehicula eu justo.
Quisque neque dolor, egestas sed venenatis eget, porta id ipsum. Ut faucibus, massa vitae imperdiet rutrum, sem dolor rhoncus magna, non lacinia nulla risus non dui. Nulla sit amet risus orci. Nunc libero justo, interdum eu pulvinar vel, pulvinar et lectus. Phasellus sed luctus diam. Pellentesque non feugiat dolor. Cras at dolor velit, gravida congue velit. Aliquam erat volutpat. Nullam eu nunc dui, quis sagittis dolor. Ut nec dui eget odio pulvinar placerat. Pellentesque mi metus, tristique et placerat ac, pulvinar vel quam. Nam blandit magna a urna imperdiet molestie. Nullam ut nisi eget enim laoreet sodales sit amet a felis.
"""
reallyLongText = _long_text + _long_text + _long_text + _long_text +_long_text
myLabel = Label(text = reallyLongText, text_size = (700,None), line_height=1.5)
print "The label size is ", myLabel.size
myLabel.size_hint_y = None
myLabel.height = 2200
return myLabel
childLayout.add_widget(longTextLabel())
scrollViewLayout.add_widget(childLayout)
return scrollViewLayout
if __name__ == '__main__':
longTextLabelApp().run()
EDIT - RST Document
Depending on your objectives it might be better to use a RSTDocument. Label are just that, labels. They don't adjust to content or text. Think of them as stickers. The (RSTDocment)[http://kivy.org/docs/api-kivy.uix.rst.html], still indicated as highly experimental though is more suitable for long texts, specially if they are dynamic. They actually includes the Scroll.
from kivy.app import App
from kivy.uix.rst import RstDocument
class RstDocumentApp(App):
def build(self):
_long_text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus odio nisi, pellentesque molestie adipiscing vitae, aliquam at tellus. Fusce quis est ornare erat pulvinar elementum ut sed felis. Donec vel neque mauris. In sit amet nunc sit amet diam dapibus lacinia. In sodales placerat mauris, ut euismod augue laoreet at. Integer in neque non odio fermentum volutpat nec nec nulla. Donec et risus non mi viverra posuere. Phasellus cursus augue purus, eget volutpat leo. Phasellus sed dui vitae ipsum mattis facilisis vehicula eu justo.
Quisque neque dolor, egestas sed venenatis eget, porta id ipsum. Ut faucibus, massa vitae imperdiet rutrum, sem dolor rhoncus magna, non lacinia nulla risus non dui. Nulla sit amet risus orci. Nunc libero justo, interdum eu pulvinar vel, pulvinar et lectus. Phasellus sed luctus diam. Pellentesque non feugiat dolor. Cras at dolor velit, gravida congue velit. Aliquam erat volutpat. Nullam eu nunc dui, quis sagittis dolor. Ut nec dui eget odio pulvinar placerat. Pellentesque mi metus, tristique et placerat ac, pulvinar vel quam. Nam blandit magna a urna imperdiet molestie. Nullam ut nisi eget enim laoreet sodales sit amet a felis.
"""
reallyLongText = _long_text + _long_text + _long_text + _long_text +_long_text
return RstDocument(text = reallyLongText)
if __name__ == '__main__':
RstDocumentApp().run()
You can set the Label to be of the size of the texture inside it like this.
FloatLayout:
Label:
# adding a background to see the amount of space the label takes
canvas.before:
Color:
rgba: .5, .5, .5, .5
Rectangle:
size: self.size
pos: self.pos
text: "How can the only thing constant in the universe be `change` when\nchange itself is by it's very nature `not constant`?"
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: None, None
size: self.texture_size
However with this you would only get a label that just expands how much text is in it and would require you to add \n yourself to make it wrap. A better approach would be to let the text inside the label auto wrap at a certain width by setting text_size something like the following::
FloatLayout:
ScrollView:
# take half of parents size
size_hint: .5, .5
pos_hint: {'center_x': .5, 'center_y': .5}
Label:
canvas.before:
Color:
rgba: .5, .5, .5, .5
Rectangle:
size: self.size
pos: self.pos
text: "\n1. Two hunters are out in the woods when one of them collapses. He doesn't seem to be breathing and his eyes are glazed. The other guy whips out his phone and calls the emergency services. He gasps, `My friend is dead! What can I do?`\n\n The operator says `Calm down. I can help. First, let's make sure he's dead.`\n\n There is a silence, then a gun shot is heard. Back on the phone, the guy says `OK, now what?`\n\n\n2. Sherlock Holmes and Dr Watson were going camping. They pitched their tent under the stars and went to sleep. Sometime in the middle of the night Holmes woke Watson up and said:\n\n `Watson, look up at the sky, and tell me what you see.`\n\n Watson replied: `I see millions and millions of stars.`\n\n Holmes said: `And what do you deduce from that?`\n\n Watson replied: `Well, if there are millions of stars, and if even a few of those have planets, it’s quite likely there are some planets like Earth out there. And if there are a few planets like Earth out there, there might also be life.`\n\n And Holmes said: `Watson, you idiot, it means that somebody stole our tent.`\n\n\n3. Three women talk about their husband is performance as lovers.\n\nThe first woman says, `My husband is a marriage counselor, so he always buys me flowers and candy before we make love.`\n\nThe second woman says, `My husband is a motorcycle mechanic. He likes to play rough and use leather sometimes.`\n\nThe third woman shakes her head and says, `My husband works for an Internet company. He just sits on the edge of the bed and tells me how great it's going to be when I get it.` \n\n\n4. As within, so outside. Fractals equations show the possibility of having infinity within minutia. Each and every cell can be a image of the whole; merging the micro and the macro into one.\n"
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 1, None
text_size: self.width, None
height: self.texture_size[1]

Definitive relationship between sizeWithFont:constrainedToSize:lineBreakMode: and contentSize (text height in Objective-C)

// textView is type of UITextView
self.textView.text = #"Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.";
CGSize maxSize = {self.textView.contentSize.width, CGFLOAT_MAX};
CGSize computedSize = [self.textView.text sizeWithFont:self.textView.font
constrainedToSize:maxSize
lineBreakMode:UILineBreakModeWordWrap];
NSLog(#"Computed size - width:%f height:%f\nContent size - width:%f height:%f", computedSize.width, computedSize.height, self.textView.contentSize.width, self.textView.contentSize.height);
Console output:
Computed size - width:320.000000 height:450.000000
Content size - width:320.000000 height:484.000000
Why are not these values equal? At least heights.
What is the .bounds.size of the text view? If all text fits within the text view the content size can still be reported as the views full size.
The UITextView is implemented using an internal web view, with allot of private magic. It is generally not a good idea to trust the text view with anything apart from displaying and editing text. The internal measurements and calculations has, and will continues to, change between OS updates.
If what you want is to change the size of the UITextView to fit all text then you must let the text view itself do this calculation. For example:
CGRect frame = textView.frame;
frame.size.height = [textView sizeThatFits:CGSizeMake(frame.size.width, CGFLOAT_MAX)];
textView.frame = frame;