Hello,
I am trying to create a TableView custom renderer for iOS and Android that will allow me to bind a custom view and apply it as a static header in either an Android ListView or an iOS UITableView. I currently have the following classes configured:
// main view
public class ExtendedTableView : TableView
{
public static readonly BindableProperty HeaderProperty = BindableProperty.Create<ExtendedTableView, View>(
p => p.Header, null);
public View Header
{
get { return (View)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
}
<!-- XAML -->
<controls:ExtendedTableView
Intent="Settings"
BackgroundColor="{x:Static res:Colors.COLOR_APP_LIGHT_BLUE}">
<controls:ExtendedTableView.Header>
<Label Text="Hello World" />
</controls:ExtendedTableView.Header>
<TableView.Root>
<TableRoot>
<TableSection>
<TextCell
x:Name="ContactUsCell"
Text="Contact Us" />
</TableSection>
</TableRoot>
</TableView.Root>
</controls:ExtendedTableView>
// ios TableViewRenderer
public class ExtendedTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TableView> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var listView = (ExtendedTableView)e.NewElement;
var _tableView = this.Control;
var headerView = RendererFactory.GetRenderer(listView.Header);
_tableView.TableHeaderView = headerView.NativeView;
}
}
}
// droid TableViewRenderer
public class ExtendedTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TableView> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
var extedned = (ExtendedTableView)e.NewElement;
var listView = this.Control;
if (extedned.Header != null)
{
var view = RendererFactory.GetRenderer(extedned.Header);
var group = view.ViewGroup;
listView.AddHeaderView(group);
}
}
}
}
The problem I'm having is that the width/height is not defined for the view at the the time that it is added to the native control in the native renderer. It works on iOS if I create a view manually and set a frame in the renderer (still haven't gotten it to work on android). I know that the height & width values are not created directly when calling RenderFactory.GetRenderer(). From my understanding there is a process in the framework that determines the height/width once it is a added to the parent view. I just don't know how to trigger the creation of the frame.
Is there a way to get something like this to work?
I don't want to use 2 separate views in my page. I need my header to scroll with the list/table rather than behind it, so I thought this would be a valid approach to try. If this is not possible -- first it would be a stellar feature to have -- second, is there a way to do something similar? I would like to have a reusable control that I can use throughout my app where I can define a TableView or a ListView and add a static header to the layout that will scroll with the list/table. Since a UITableView or ListView scrolls independently, I'm not sure how it would work to wrap everything in a scroll view.
I am open to suggestions in any facet. I'd like to get this custom control to work if its possible, otherwise an alternative approach would work too.