Custom RecyclerView for Forms - xamarin

I'm having an issue when displaying a large number of visual elements in a scroll viewer, and I've tried every possible way to achieve the same approach, either with 3rd party horizontal list views (Can't find one with variable column/element width) or with rotated native list view (gives weird results).
The only approach that gives the result is via stacklayout docked in scrollviewer where I populate that stacklayout from code. Now the problem is all elements are rendered even if they were not displayed, so it makes the application either very slow.
I thought about having a recyclerview (which exists in native android) but I can't find an approach for it forms as it only exists in android. Now can anyone help me with that? Maybe a custom view where it uses recycler view on android and any similar approach or maybe a regular scrollviewer on iOS ?
Thanks in advance.
Update #1
I could do the rotated listview option using this code -Inspired by this answer-
<RelativeLayout>
<ListView ItemsSource="{Binding Entries}" Rotation="-90" HasUnevenRows="True"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-37}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=-0.5, Constant=37}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<BoxView Rotation="90" BackgroundColor="Beige" WidthRequest="200"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RelativeLayout>
But I can never make this box view fill the while cell, there is always empty space -The box view is a place holder instead of other custom control-.
Is there a method to make the box view always fill the whole cell height and fill and expand it to it's WidthRequest property -Which will be dynamic according to a binding later- ?

I have found a workaround for such an issue by using a listview with custom template, where I inside of it I used several scrollviews and linked their movement together. Refer to my answer here: How to make multiple list views scroll together?

Related

How to make this progress bar vertically in xamarin forms

I want to create this ui design in xamarin forms, as progress bar should look like this vertically.
To make the ProgressBar vertical, I have an easy solution for that.You can refer to the XAML below. It could help you.
Xaml:
<StackLayout Rotation="-90" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
<ProgressBar Progress="1" ProgressColor="Orange" >
</ProgressBar>
</StackLayout>

Xamarin Forms Rotated ListView Spins on Redraw

To make a chat page, I followed an example I found that sets the ListView rotation to 180, so the list builds from the bottom and then set things in the DataTemplate to rotate 180, so the items will be upright. It's a great solution, but when the keyboard opens, the ListView gets shorter which causes a redraw. During the redraw, the ListView initially appears with rotation 0 and I see an animation as if RotateTo(360) is being called. After initially displaying, I get to watch the list view rotate around in full circle. Click off the message editor, and the ListView gets taller, and it does it again.
Has anyone seen this?
Here's what the Xaml looks like. I can't make a gif of what it looks like, but imagine watching:
MessageList.Rotation = 0;
MessageList.RotateTo(360, 500, Easing.Linear);
each time the keyboard shows and hides, and you'll get the idea...
<ListView
X:Name="MessageList"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1"
Rotation="180"
ItemsSource="{Binding ChatMessages}"
SelectionMode="None"
HasUnevenRows="True"
SeparatorColor="Transparent">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame
BackgroundColor="LightGray"
FlowDirection="LeftToRight"
Rotation="180"
Padding="10"
HasShadow="false"
Margin="80,2,0,5">
<Label Text="{Binding ChatText}"/>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I followed the same tutorial you mentioned and you are probably using a ContentPage renderer to handle your keyboard layout updates on iOS. If you check the sample project https://github.com/rdelrosario/ChatUIXForms you'll notice he resizes the keyboard ContentView with a ContentView renderer for the Editor box at the bottom using the Margin property, rather than the entire ContentPage. Which doesn't trigger the above issue.
What I wound up doing was to make a custom ListView renderer that was keyboard aware in iOS and sets a translation X to move the top of the listview up when the keyboard appears and back down when it goes away. As a result, the listview is not getting resized, and thus does not redraw.
It may be messy, but it makes it work...

HeightRequest on ListView calculates weird?

I've heard a couple things about ListView.
it takes up the full height of its container
on iOS it just goes ahead and adds empty rows until it takes up the full height
you have to use HasUnevenRows=True to be able to set its height even if all your rows are the same height.
It sure would be great if there were a way to get ListView to not display those extra empty rows though, right? Well, that's what I am trying to do.
<ListView
BackgroundColor="Green"
ItemsSource="{Binding Things}"
HasUnevenRows="True"
HeightRequest="5"> <!-- In the real code I am setting this in a ValueConverter. It's hard coded here for simplicity. -->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="This is text." />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Except I don't even know what it could possibly be doing. Here I use HeightRequest=5 and HeightRequest=50 there is a difference. But I can't tell what it is.
What's going on here?
Now this is a very interesting question. We have had similar issues with ListViews as unfortunately that unlimited scrolling is actually a standard behaviour on iOS, so you have to think of way around it. The way we have done it is basically count the amount of items within the list, this is pretty straight forward, because you only have to call for ListOfItems.Count. Next thing you want to do, you want to get the Height of your Single DataTemplate item. When you do that then just multiple count of your items by Height of single item and set that Value to HeightRequest. It is not ideal, but it does a job.
I understand why this works. What I don't understand is why the 50 other ways I tried did not work. So from that point of view I have no idea why this works.
Wrap it in a StackLayout:
<StackLayout>
<ListView
BackgroundColor="Green"
ItemsSource="{Binding Things}"
HasUnevenRows="True"
HeightRequest="5"> <!-- In the real code I am setting this in a ValueConverter. It's hard coded here for simplicity. -->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="This is text." />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
It might seem relevant at first but I'm not sure. My ListView was in a grid so it had
<ListView
Grid.Row="1"
Grid.Column="1"
... />
Which got moved into the StackLayout. Again, I know that seems glaringly relevant but I have my doubts. Unfortunately I don't have the time to rip everything out just to test that idea out.

long list selector not scrolling properly

My LongListSelector is not scrolling properly. When I scroll the list, it automatically reaching back to the top with its rubber band effect.
xaml is
<Grid x:Name="ContentPanel" Height="2000">
<toolkit:LongListSelector x:Name="ItemList" DataContext="Item" IsFlatList="True" StretchingBottom="LoadMoreData">
<toolkit:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid Tag="{Binding ItemID}" Loaded="Grid_Loaded" MaxWidth="361" MaxHeight="100">
// some xaml code
</DataTemplate>
</toolkit:LongListSelector.ItemTemplate>
</toolkit:LongListSelector>
</Grid>
can anyone help me ?
thanku
It's not scrolling correctly because you set the Height of the parent Grid to 2000. This causes the LongListSelector to take as much space as it may need as long as it's less than 2000 and only then starts scrolling. Considering you only have 800 (or a bit more) of height, you don't see the scrolling properly.

WP7 - ListPicker in StackPanel in ScrollViewer

Just started with developing for WP7 and came across the following. I have a pivot application with a few pivotitems. On the first pivotitem (see code below) I want to be able to adjust a lot of settings. For this question all items to be set are called 'TextBox' and the choice in the ListPicker is either A,B or C.
Now if I do NOT use the ScrollViewer and I tap any of the listpickers I get to see all three options BUT I can not scroll through all listpickers.
If I DO use the ScrollViewer, I CAN see all listpickers but only the top one (that's visible) will expand and give me the options A,B and C, they others stay collapsed.
How can I get every listpicker to expand and show me the avaiable options AND be able to scroll to every listpicker on the page?
PS In code below copy the stackpanel between start and end about 15 times.
Thanks in advance for any help!
<controls:PivotItem Header="blabla">
<ScrollViewer>
<StackPanel Margin="0,0,36,0" VerticalAlignment="Top" d:LayoutOverrides="Width">
// start
<StackPanel Orientation="Horizontal">
<TextBlock TextWrapping="Wrap" Text="TextBox" Width="80" TextAlignment="Right" Margin="10,22,20,0" HorizontalAlignment="Right" VerticalAlignment="Top" />
<toolkit:ListPicker Margin="0" Width="275">
<toolkit:ListPickerItem Content="A"/>
<toolkit:ListPickerItem Content="B"/>
<toolkit:ListPickerItem Content="C"/>
</toolkit:ListPicker>
</StackPanel>
// end - copy/paste code code between start and end about 15 times right here
</StackPanel>
</ScrollViewer>
</controls:PivotItem>
This is, apparently, a common issue with Listpicker and ScrollViewer. You can find a workaround here
Should anybody stumble upon this, this has been fixed since the november 2011 release of the wP7 silverlight toolkit.

Resources