Fill a Grid Cell with a scaled View - user-interface

I want to fill a space in a Grid with a View which got scaled down (Scale="0.5"). Assume I have a Grid with three rows and two columns, and the scaled down View should fill Grid.Row="1" Grid.Column="1" like this (outlined in red):
The problem I'm running into is that the View will get scaled down, but it doesn't re-position itself in the grid. The former size is still dominant for how big the cells of the grid actually is:
Seeing this result, I see two problems:
HorizontalOptions are not executed after the scaling happens
Grid Cell height is not being updated to fit the new height of the scaled view
As you can see in the first image, I achieved to scale it down and respect the Grid size. However, this is in a very hacky way by translating the View with hard coded values to the right position. So as soon as I add any new views to this Page, the positioning of the scaled down View will be wrong.
This is my (simplified) code:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--Other Views...-->
<CircularView
Grid.Row="3"
Grid.Column="0"
</CircularView>
<Grid
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
Scale="0.5"
VerticalOptions="CenterAndExpand"
HeightRequest="240"
IsVisible="{Binding HasTermine}">
<MyCustomView/>
</Grid>
<!--Other Views...-->
</Grid>
I'm using ColumnSpan="2" so that I have a width of exactly one column after using Scale="0.5", but this might already be a wrong approach and I would definitely prefer to not do it this way. Also tried changing the HeightRequest to 120 after the scaling happens, but this will also shorten the height of MyCustomView.
What is the optimal approach to fill a Grid Cell with a scaled down View?
Sample Repository:
https://github.com/Zure1/ScaleSample/

I did some test and can't a way to fill a Grid Cell with a scaled down View.
You can open a free Xamarin support case here: supportforXamarin to get more help and find if there is any solution to it.
Instead of use a scaled down View, I use a View with grid layout to achieve the similar requirement as yours and I upload a sample(based on you) here: resizeView-xamarin.forms. You can have a look at it and maybe you can find some idea from it. Hope it make sense to you.

Related

Xamarin Forms listview out of memory error

In Xamarin Forms i have the following listview:
<ListView x:Name="StudentView" RowHeight="55" SeparatorVisibility="None" CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="55"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Image Source="{Binding Image}" Grid.Row="0" Grid.Column="0" Aspect="AspectFill"></Image>
<Image Source="{Binding Image}" Grid.Row="0" Grid.Column="1" Aspect="AspectFill"></Image>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
In the code behind i have declared an array of 1000 items.
The problem is that if i scroll up and down the listview, everytime i see in the xamarin profile that the memory usage increase and seems that CachingStrategy="RecycleElement" not work properly (tested on real android device).
After scroll some times, the program crash with out of memory.
What's the problem? How can i resolve it?
Not sure how you are setting the ItemSource of the list view, or what it is. It would be useful to also show some of the code-behind file for this.
As a blind guess there can be performance issues with the recycling if your source is not indexable. The recommendation from Xamarin is to use an IList for the itemsource, using something like an IEnumerable will cause performance issues for a large array because it essentially has to keep looping through the data to find the right item for display.
1000 Image items are a lot! I bet this is Android, I suggest to use different solutions like:
1.- Pagging strategies (Load 10, the load another 10 and so).
2.- Reduce the images sizes.
3.- Use a cacheable image like:
https://github.com/luberda-molinet/FFImageLoading
4.- Implement a View custom renderer with a Recycler view.
And then the topic gets bigger and bigger on how you can improve your ListView performance, here are some useful links:
-https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/performance/
-https://blog.xamarin.com/creating-highly-performant-smooth-scrolling-android-listviews/
-https://blog.xamarin.com/tips-for-creating-a-smooth-and-fluid-android-ui/
-http://kent-boogaart.com/blog/jason-smith's-xamarin-forms-performance-tips
I had the same issue , large list of images or images with large resolution causes this problem, I solved this by using FFImageLoading found here, also available on nuget , Also try to bind thumbnails instead of the actual Image if possible.
<ContentPage xmlns:ci="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms">
<ci:CachedImage Source="{Binding ActualImageThumbnail}" Aspect="Fill"/>

Windows Phone 7 - how to determine which row should resize when keyboard is visible?

My problem is that I've got grid with rows:
<Grid.RowDefinitions>
<RowDefinition Height="139"/>
<RowDefinition Height="72" />
<RowDefinition Height="482*" />
<RowDefinition Height="75" />
</Grid.RowDefinitions>
and I want to have top of the third row visible when keyboard shows up, but unfortunatelly everything goes up (above visible area).
How to fix it? I've thought about determining somehow which row should resize, but I don't know if it is possible.

How to show a large grid of buttons in a panorama item over 3 screens?

i made a very wide grid with multiple rows and columns, and i filled the grid with buttons (there is no vertical scrolling). All that is contained in one panorama item. Approx. 3 screen widths are needed to cover the whole grid in horizontal scrolling (about 1500 px wide).
So the problem is when the user flicks the screen in panorama - it jumps from the beginning of the panorama item all the way to the end of it. So effectively only the far left and far right side of the grid is available to the user (only if he scrolls really slowly, he can get to the rest of the content in the middle).
Ideally, i would have three panorama items, with the content overlapping over all of them - so the content can be viewed with two flicks - but i can't achieve that. Is it possible to overlap the grid over 3 panorama items? Or maybe, is it possible to somehow add some kind of stops in the middle or divide that one panorama item that i currently have so that the screen stops somewhere in the middle?
I can't find any examples for more than 2 screens, and wrapping doesn't work for me - i want a fixed height and i can't make buttons any smaller in width. Anyway, i even don't know is it possible to achieve all this? Maybe i'm overstreching the panorama capabilities...
Thank you
Edit:
This would be an example of my problem (i have over 100 buttons so the xaml code is very large but this is the same basic problem i am trying to solve):
<controls:PanoramaItem Header="first item" Orientation="Horizontal">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="500" />
<ColumnDefinition Width="500" />
<ColumnDefinition Width="500" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0"
Grid.Column="0"
Width="250"
Height="250"
Content="Button1" />
<Button Grid.Row="0"
Grid.Column="1"
Width="250"
Height="250"
Content="Button2" />
<Button Grid.Row="0"
Grid.Column="2"
Width="250"
Height="250"
Content="Button3" />
</Grid>
</controls:PanoramaItem>
So if you put this into your panorama control - you get a very wide panorama item - and if you flick it from Button1 it jumps all the way to the far right on the Button3 - so it scrolls you past the Button2... I want it to stop scrolling on the Button2.
You may want to investigate setting the Orientation property to Horizontal for your PanoramaItem, which should produce the effect you are looking for :-
<controls:PanoramaItem Header="first item" Orientation="Horizontal">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0"
Grid.Column="0"
Width="250"
Height="250"
Content="Button1" />
<Button Grid.Row="0"
Grid.Column="1"
Width="250"
Height="250"
Content="Button2" />
<Button Grid.Row="0"
Grid.Column="2"
Width="250"
Height="250"
Content="Button3" />
</Grid>
</controls:PanoramaItem>
Hope this helps.
Paul Diston
OK, i did research on this problem, and the answer is that i was really overstreching panorama item capabilities.
So, if one would want to achieve that what i was trying to achieve - that is to get one panorama item to stretch over 3 screen widths - the best way to go is to make 3 separate panorama items and try to set the margins of each one manually so the user feels like he's browsing the one and the same panorama item (seamlessly switching from one to another).
In other words, one panorama item is optimized for max 2 screen widths, and that would be my answer. Anything over 2 screens and you loose the flick gesture behaviour, so you lose that content in the middle.

How to make UI adjust the length and width according to the size of the text?

I have done localization of my app. The problem that I'm facing is that, a single line of text may be 2 lines in chinese or some other language. It would be easier if the text blocks or buttons would increase the size according to the size of the text.
Is there any way out for this? Else I would have to fix the length and width to the maximum used by the language, but then some languages may not use up so much space and it will look odd.
Alfah
Rather than using fixed width / height, it is better to create a layout which allows the TextBlock to adjust its width. For example, if you have a two column layout, setting the column widths to Auto will cause the column to grow to accomodate its widest element:
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="This is a label:"/>
<TextBox Text="This is a value" Grid.Column="1"/>
</Grid>

Align TextBlocks by baseline

I have two TextBlocks, each with a different font size, and am trying to align them vertically so that their baselines match up.
I know how to do this by creating multiple Run elements within a single TextBlock, but in this case my TextBlocks are not directly adjacent, so that won't work. Here's a simplified example of my layout:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0"
FontSize="20"
VerticalAlignment="Bottom">Small</TextBlock>
<TextBlock Grid.Column="1"
FontSize="50"
VerticalAlignment="Bottom">Large</TextBlock>
</Grid>
If I could find a way to calculate the baseline of the font in code, that would be good enough - I could do the alignment in code, using a Canvas or custom Panel - but I haven't been able to find any WP7 APIs for finding font metrics.
I have found a very similar question here, but the solution involves the FormattedText class, and unfortunately this is not available on WP7.
I would really like to be able to do this without hardcoding any margins/offsets, if possible.
Whilst I agree with Matt's answer, if you actually need to solve the problem without manually setting margins, etc, then you can align them "properly" by setting the LineHeight to the tallest line, and then setting LineStackingStrategy to BlockLineHeight.
In that you are hardcoding the fontsizes in XAML, what's so bad about hardcoding margins to create the effect you are looking for?
This will also mean that you only need to do the calcuation once, rather than forcing the app to do it every time the page is laid out.

Resources