I have problems with my font sizes on big screens.
By default, my label looks perfect on my small android phone.
<Label HorizontalTextAlignment="Center"
Text="Lobby"
FontSize="16" />
When I switch to my Amazon Fire Tablet, the label is very, very tiny. Almost everything is too tiny.
I have read, there is a unit "sp" for Android projects. Is there a built in way to do it in Xamarin.Forms? Are there libraries that could help me with that?
I already took a look at:
Resolution-dependent font size in Xamarin. Unfortunately I am using Xamarin.Forms.
Thanks in advance!
You can use the NamedSize enum for font sizes.
The available ones are :
Micro
Small
Medium
Large
Eg:
<Label Text="Login" FontSize="Large"/>
<Label Text="Instructions" FontSize="Small"/>
Try use Device.Idiom if you are using PCL. Depend of type of device, you can add a different image size.
https://developer.xamarin.com/api/type/Xamarin.Forms.Device/
https://developer.xamarin.com/api/property/Xamarin.Forms.Device.Idiom/
And this extended guide - https://developer.xamarin.com/guides/android/application_fundamentals/resources_in_android/part_4_-_creating_resources_for_varying_screens/
Related
In my login UI, I have a footer image, which is showing perfectly in small devices. But on big screen devices (mainly on iPad) it is not showing fully.
I tried all Aspect property of Image, but not worked.
Screenshot:
I try a lot to fix this but didn't get a solution.
Attaching the LoginPage.xaml file with this question. Please suggest a solution for this issue. :)
Make sure (in the iOS project -> Assets) your image set has 3 different sizes xxx.png,xxx.png#2x and xxx.png#3x .
Which image will be used for your app? That depends on the device your app is viewed on. Higher resolution devices (larger and newer devices) have more pixels on their screens. Thus they need higher resolution images to display properly without any blurring.
If you don’t supply the higher resolution (#2x or #3x) images, your app will automatically try to scale the #1x image up. This is not good and can result in a distorted or blurry image!
Based on the file you linked in the comments, I think it would suffice to remove the bottom StackLayout wrapping the Image, and instead put Grid.Row="1" & VerticalOptions="End" to the bottom Image.
Please update your question with the relevant code to make the question and answers more helpful to others.
Remove latest StackLayout with image and add it after StackLayout with Grid.Row="1" like this
<Grid Grid.Row="1"
BackgroundColor="#c0eefb">
<Image
Source="ic_footer_image_xx.png"
Aspect="AspectFill"
HorizontalOptions="FillAndExpand"/>
</Grid>
I have a nativescript-vue app with the RadListView component to display data to the user. Each row of the list include multiple informations for the current item. When i tap on a button to load and show the list the UI freeze (fast hardware -> short; slow hardware -> long). I figured out that the code part to load/combine the data run very short but the nativescript-internal rendering or creation of the UI elements are the problem. The android console show the information
I/Choreographer: Skipped 430 frames! The application may be doing too much work on its main thread.
Platform info:
tns-ios 5.2.0
tns-android 5.2.1
nativescript-ui-listview 6.2.0
tns-core-modules 5.3.1
Similar problem reports
I look at stackoverflow and github but the problems there (e.g. NativeScript Angular RadListView rendering extremely slowly) looks similar but the solutions not suitable for me.
I use the LinearListView (not Grid nor Stagged) and maybe in my real app i will be able to simplify the row elements from the list but in my sample app (look down) i use a simple row ui design.
Sample app
For a simpler and better report i created a sample app on the {N}-Playground. The app creates 10000 array elements and set them as source of the RadListView which has a Label, a Switch and an ActivityIndicator for every element.
<RadListView ref="listView"
for="alarm in alarms"
layout="linear">
<v-template>
<StackLayout class="list-element" orientation="vertical" >
<GridLayout columns="*, auto, auto" rows="*">
<Label col="0" row="0">{{alarm.name}}</Label>
<Switch col="1" row="0" :checked="alarm.active" />
<ActivityIndicator col="2" row="0" :busy="alarm.active"/>
</GridLayout>
<Label class="list-element-divider"></Label>
</StackLayout>
</v-template>
</RadListView>
In the first step the 10000 elements will be generated in a temporary array:
loadData() {
this.tmpAlarms = [];
for (let i = 0; i <= 10000; i++) {
this.tmpAlarms.push({
name: "Hase " + i,
active: i % 2 === 0,
});
}
}
With a second button set the temporary array as source:
setData() {
this.alarms = this.tmpAlarms;
}
Note: I use 10000 elements to make the problem visible even the sample app runs on a S9 or another high end smartphone.
The full source is runnable under https://play.nativescript.org/?template=play-vue&id=Td1GWR
A slightly different version with an ObservableArray instead of a plain array is under https://play.nativescript.org/?template=play-vue&id=5BXOFG
In both versions the data handling is fast but as soon the UI elements generated from the internal functions the UI will be frozen.
Sample: On my Nexus 7 2013 with Android 6.x the UI freeze nearly 6 seconds and no other apps running in background.
iOS
If i try the same apps on an iOS device (e.g. iPhone 7s) the rendering is very fast and the UI running smooth even so with the 10000 elements and more.
Ideas?
Have anyone an idea how i can speed up the rendering? If not is there a suggestion how i can build an animation (e.g. ActivityIndicator) to show the user that the device is working? At the moment when i put an ActivityIndicator on the UI the user can not see it because of the frozen UI.
Android and IOS have a very different way of rendering the ui. This difference added to particularity of the Rad list can affect performance. Note that the rad list reuse the instance of the list element to improve performance. This reuse is not done the same way in IOS and in Android.
There are two simple optimizations that can improve a lot the rendering in ios and android.
The first one is to reduce the layouts in layouts. It is easier for the rendering if there are less elements. This reduce the depth/passes rendering
<RadListView ref="listView" for="alarm in alarms" layout="linear">
<v-template>
<GridLayout class="list-element" columns="*, auto, auto" rows="*, auto">
<Label col="0" row="0">{{alarm.name}}</Label>
<Switch col="1" row="0" :checked="alarm.active" />
<ActivityIndicator col="2" row="0" :busy="alarm.active"/>
<Label colSpan="3" row="1" class="list-element-divider"></Label>
</GridLayout>
</v-template>
</RadListView>
The second is the one that have the most impact. Set an height to component when possible. Here the use of *,auto,auto will means that it will have to recalculate for each elements of the list. And here is where IOS and Android differs.
IOS will re render only what is required in the element. This means that the stack layout and the grid layout will stay the same when the element is recycled but if the content of the grid layout would be bigger in lower elements, the rendering on IOS may be all wrong the more you scroll. This is really faster because no need to adjust the height each time. But can be bad if size need to change.
Android tends recycle but to rerender all the components and therefore recalculate for each. This is slower but safer for size change.
In general, setting and height will boost the performance of the app because there are less inference form the rendering engine that need to be done. This is true everywhere in your app but really important in rad list.
I am developing in Xamarin forms, and I have a Label that can contain a varying amount of text.
The platforms I use in forms are primarily: Android and UWP (no need for iOS ATM).
I want to give this label a background that is not rectangular and that is something more like this: (chat/message bubble style)
I have read about some possible solutions but I'm confused from all the options that are available.
From what I understand of my research around this and from my work with other platforms there are basically two options:
Set an image background.
Use Custom graphic controls to create the shape I want.
I'm not sure how to implement any of these options in Xamarin Forms, I'll be glad to get some help.
The easy solution would be to host the Label inside a View and set have an Image behind the label:
<Grid>
<Image Source="message_background.png">
<Label Text="{Binding Message}">
</Grid>
This is not very performant if you're going to have a lot of these on screen. The best solution would then be to use a custom renderer for each platform an implement it natively. This would give much better performance much more flexibility. It's more maintenance and initial work though.
You can read up on custom renderers here
I have decided to try Xamarin Forms, because I thought that I can make one design for all platforms or at least Android and iOS.
However a simple form like:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:app91="clr-namespace:App9;assembly=MasterDetail.Android"
x:Class="MasterDetail.CompetitorsListPage"
>
<StackLayout>
<Label Text="{Binding CurrentEvent.Name}"></Label>
<StackLayout Orientation="Horizontal">
<Button Text="By Place" Clicked="Button_OnClickedByPlace"></Button>
<Button Text="By Number" Clicked="Button_OnClickedByNumber"></Button>
<Button Text="By Rating" Clicked="Button_OnClickedByRating"></Button>
<Button Text="Change Event" Clicked="Button_OnClickedChangeEvent"></Button>
</StackLayout>
<ScrollView>
<ListView x:Name="couples" ItemSelected="Comps_OnItemSelected" ItemTapped="Couples_OnItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Round}"></Label>
<Label Text="{Binding Pos, StringFormat='({0}).'}"></Label>
<Label Text="{Binding Name}"></Label>
<Label Text="{Binding StartingNumber}" ></Label>
<Label Text="{Binding OldRating, StringFormat=' [{0}]'}"></Label>
<!--<Label Text="{Binding NewRating, StringFormat=' {0} ]'}"></Label>-->
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</StackLayout>
</ContentPage>
Looks completely different on Android and iOS. I do not mind colours, but font size? I do not set font anywhere in the code or xaml.
Any idea what am I doing wrong?
Here it is a picture showing both versions:
This is by design. Forms is intended to provide a native experience on each platform by using their respective UI standards. Android has a different default color scheme than iOS. iOS default buttons look different than Android.
You can override the default fonts, sizes, colors, etc if you like in order to provide a more consistent UI. Xamarin has also introduced Themes for Forms which help you provide a consistent UI between platforms.
Because Android has variety of screen sizes and different screen DPI as compared to standard dpi and font sizes across iOS devices, it is not possible to create same look. But you can certainly change Theme in the MainActivity of your Droid project and increase font size as per your convenience. Beware that your theme's font size may be too big for small devices and too small for big devices. You can add scaling factor for font size in your theme, but I have not been very successful, instead, I tried to design a UI that will automatically fit for the best.
As per Xamarin Evolve 2016, some questions were raised regarding font sizes, they said it is difficult, but they are trying to make some unified font sizing.
Although Xamarin.Forms has everything in Xaml and C#, you still need to use iOS assets and Android resources to customize look and feel.
For me, #Jason's answer and comments from #Egg and #Bill Reiss are spot-on.
Meanwhile, so often clients request "same font size" across platforms that something like this finds its way into base Styles or Theme to account for what seems to be "natively smaller" fonts on Android:
<OnPlatform x:TypeArguments="Font">
<OnPlatform.iOS>Bold,Medium</OnPlatform.iOS>
<OnPlatform.Android>Bold,Large</OnPlatform.Android>
<OnPlatform.WinPhone>Bold,Medium</OnPlatform.WinPhone>
</OnPlatform>
Something similar can also be expressed in code at or near app startup, for example as a base Label font added to global Styles dictionary.
Just wanted to give a concrete example of what others above alluded to.
Strange behavior on iOS - as you can see those are labels in StackLayout, while in Android they behave OK, in iOS second and third label behave more lithe they were in some kind of grid rather than stack –
You have put 5 labels in a horizontal stack, and haven't changed the layout options on any of them. This will 'stack' all 5 labels next to each other, then size them based on the amount of text to be displayed. There is not enough horizontal space to accommodate all of the text, so the labels are wrapping vertically. The longest labels show the most wrapping, but as they get longer other labels wrap as well, which is why the Pos and OldRating data raps in some labels. When I'm working out layouts like this I often add different background colors to each control so I can see how they are laying out.
There are different ways to solve this depending on your desired result. If you want the entire line of text to wrap you can concatenate the data behind the scenes and add it as one label. If you want the name to wrap and the other data to display without wrapping you can set WidthRequests on the labels.
I am working at a WinRT application that implies some manipulations of an image at a WriteableBitmap level. On my page, I have ofcourse an image that shows the processing results. My objective now, is slightly different though, I would like to know if there is any way I could acces through code the built-in zoom in/out that could be achieved through pinch mode if on touch device on control + mouse wheel if on PC.
Here's a bit of my code where I've got the image :
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Image Grid.Row="0" x:Name="ImagePanel" Stretch="Uniform" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</ScrollViewer>
I am asking this in case anyone might know if this can be achieved only because the zoom is very optimized and can be extremely useful :)
Thank you, any help or suggestions are greatly appreciated.
The ScrollViewer has a ZoomFactor property and a ZoomToFactor() method you can use.