2016-08-13 07:30:41 +03:00
|
|
|
|
using System;
|
|
|
|
|
using Android.Widget;
|
|
|
|
|
using Bit.Android.Controls;
|
|
|
|
|
using Bit.App.Controls;
|
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
using Xamarin.Forms.Platform.Android;
|
2016-08-18 06:57:14 +03:00
|
|
|
|
using Android.Content;
|
|
|
|
|
using AView = Android.Views.View;
|
|
|
|
|
using AListView = Android.Widget.ListView;
|
|
|
|
|
using Android.Views;
|
2016-08-13 07:30:41 +03:00
|
|
|
|
|
|
|
|
|
[assembly: ExportRenderer(typeof(ExtendedTableView), typeof(ExtendedTableViewRenderer))]
|
|
|
|
|
namespace Bit.Android.Controls
|
|
|
|
|
{
|
|
|
|
|
public class ExtendedTableViewRenderer : TableViewRenderer
|
|
|
|
|
{
|
2016-08-19 02:09:01 +03:00
|
|
|
|
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
|
|
|
|
|
{
|
|
|
|
|
base.OnElementChanged(e);
|
|
|
|
|
Control.Divider = null;
|
|
|
|
|
Control.DividerHeight = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-18 06:57:14 +03:00
|
|
|
|
protected override TableViewModelRenderer GetModelRenderer(AListView listView, TableView view)
|
|
|
|
|
{
|
|
|
|
|
return new CustomTableViewModelRenderer(Context, listView, view);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-13 07:30:41 +03:00
|
|
|
|
public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
|
|
|
|
|
{
|
|
|
|
|
var baseSize = base.GetDesiredSize(widthConstraint, heightConstraint);
|
|
|
|
|
var height = ComputeHeight(Control, Convert.ToInt32(baseSize.Request.Width));
|
2016-08-21 07:50:48 +03:00
|
|
|
|
return new SizeRequest(new Size(baseSize.Request.Width, height));
|
2016-08-13 07:30:41 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-18 06:57:14 +03:00
|
|
|
|
private int ComputeHeight(AListView listView, int width)
|
2016-08-13 07:30:41 +03:00
|
|
|
|
{
|
2016-08-19 07:27:37 +03:00
|
|
|
|
var element = Element as ExtendedTableView;
|
|
|
|
|
|
2016-08-13 07:30:41 +03:00
|
|
|
|
var adapter = listView.Adapter;
|
|
|
|
|
var totalHeight = listView.PaddingTop + listView.PaddingBottom;
|
2016-08-21 07:50:48 +03:00
|
|
|
|
var desiredWidth = MeasureSpec.MakeMeasureSpec(width, MeasureSpecMode.AtMost);
|
2016-08-13 07:30:41 +03:00
|
|
|
|
for(var i = 0; i < adapter.Count; i++)
|
|
|
|
|
{
|
2016-08-19 07:27:37 +03:00
|
|
|
|
if(i == 0 && (element?.NoHeader ?? false))
|
|
|
|
|
{
|
2016-08-20 08:17:13 +03:00
|
|
|
|
totalHeight += 1;
|
2016-08-19 07:27:37 +03:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-13 07:30:41 +03:00
|
|
|
|
var view = adapter.GetView(i, null, listView);
|
|
|
|
|
view.LayoutParameters = new LayoutParams(LayoutParams.WrapContent, LayoutParams.WrapContent);
|
2016-08-21 07:50:48 +03:00
|
|
|
|
view.Measure(desiredWidth, MeasureSpec.MakeMeasureSpec(0, MeasureSpecMode.Unspecified));
|
2016-08-13 07:30:41 +03:00
|
|
|
|
totalHeight += view.MeasuredHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return totalHeight + (listView.DividerHeight * (adapter.Count - 1));
|
|
|
|
|
}
|
2016-08-18 06:57:14 +03:00
|
|
|
|
|
|
|
|
|
private class CustomTableViewModelRenderer : TableViewModelRenderer
|
|
|
|
|
{
|
2016-08-19 02:09:01 +03:00
|
|
|
|
private readonly ExtendedTableView _view;
|
2016-08-18 06:57:14 +03:00
|
|
|
|
private readonly AListView _listView;
|
|
|
|
|
|
|
|
|
|
public CustomTableViewModelRenderer(Context context, AListView listView, TableView view)
|
|
|
|
|
: base(context, listView, view)
|
|
|
|
|
{
|
2016-08-19 02:09:01 +03:00
|
|
|
|
_view = view as ExtendedTableView;
|
2016-08-18 06:57:14 +03:00
|
|
|
|
_listView = listView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ITableViewController Controller => _view;
|
|
|
|
|
|
2016-08-22 07:49:52 +03:00
|
|
|
|
// ref http://bit.ly/2b9cjnQ
|
2016-08-18 06:57:14 +03:00
|
|
|
|
public override AView GetView(int position, AView convertView, ViewGroup parent)
|
|
|
|
|
{
|
|
|
|
|
var baseView = base.GetView(position, convertView, parent);
|
2016-08-19 02:09:01 +03:00
|
|
|
|
var layout = baseView as LinearLayout;
|
2016-08-22 07:49:52 +03:00
|
|
|
|
if(layout == null)
|
|
|
|
|
{
|
|
|
|
|
return baseView;
|
|
|
|
|
}
|
2016-08-19 02:09:01 +03:00
|
|
|
|
|
2016-08-18 06:57:14 +03:00
|
|
|
|
bool isHeader, nextIsHeader;
|
2016-08-22 07:49:52 +03:00
|
|
|
|
var cell = GetCellForPosition(position, out isHeader, out nextIsHeader);
|
2016-08-21 07:50:48 +03:00
|
|
|
|
if(layout.ChildCount > 0)
|
|
|
|
|
{
|
|
|
|
|
layout.RemoveViewAt(0);
|
2016-08-22 07:49:52 +03:00
|
|
|
|
var cellView = CellFactory.GetCell(cell, convertView, parent, Context, _view);
|
|
|
|
|
layout.AddView(cellView, 0);
|
2016-08-21 07:50:48 +03:00
|
|
|
|
}
|
2016-08-19 02:09:01 +03:00
|
|
|
|
|
2016-08-18 06:57:14 +03:00
|
|
|
|
if(isHeader)
|
|
|
|
|
{
|
2016-08-27 01:42:28 +03:00
|
|
|
|
var textCell = layout.GetChildAt(0) as BaseCellView;
|
2016-08-19 02:09:01 +03:00
|
|
|
|
if(textCell != null)
|
|
|
|
|
{
|
2016-08-22 07:49:52 +03:00
|
|
|
|
if(position == 0 && _view.NoHeader)
|
2016-08-19 02:58:25 +03:00
|
|
|
|
{
|
|
|
|
|
textCell.Visibility = ViewStates.Gone;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
textCell.MainText = textCell.MainText?.ToUpperInvariant();
|
2016-08-21 07:50:48 +03:00
|
|
|
|
textCell.SetMainTextColor(Color.FromHex("777777"));
|
2016-08-19 02:58:25 +03:00
|
|
|
|
}
|
2016-08-19 02:09:01 +03:00
|
|
|
|
}
|
2016-08-18 06:57:14 +03:00
|
|
|
|
}
|
2016-08-27 01:42:28 +03:00
|
|
|
|
|
|
|
|
|
var bline = layout.GetChildAt(1);
|
|
|
|
|
if(bline != null)
|
2016-08-18 06:57:14 +03:00
|
|
|
|
{
|
2016-08-27 01:42:28 +03:00
|
|
|
|
bline.SetBackgroundColor(_view.SeparatorColor.ToAndroid());
|
2016-08-18 06:57:14 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-22 07:49:52 +03:00
|
|
|
|
return layout;
|
2016-08-18 06:57:14 +03:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-21 07:50:48 +03:00
|
|
|
|
// Copy/pasted from Xamarin source. Invoke via reflection instead maybe?
|
|
|
|
|
private Cell GetCellForPosition(int position, out bool isHeader, out bool nextIsHeader)
|
2016-08-18 06:57:14 +03:00
|
|
|
|
{
|
|
|
|
|
isHeader = false;
|
|
|
|
|
nextIsHeader = false;
|
|
|
|
|
|
|
|
|
|
var model = Controller.Model;
|
|
|
|
|
var sectionCount = model.GetSectionCount();
|
|
|
|
|
|
|
|
|
|
for(var sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++)
|
|
|
|
|
{
|
|
|
|
|
var size = model.GetRowCount(sectionIndex) + 1;
|
|
|
|
|
if(position == 0)
|
|
|
|
|
{
|
|
|
|
|
isHeader = true;
|
|
|
|
|
nextIsHeader = size == 0 && sectionIndex < sectionCount - 1;
|
2016-08-21 07:50:48 +03:00
|
|
|
|
|
|
|
|
|
var header = model.GetHeaderCell(sectionIndex);
|
|
|
|
|
Cell resultCell = null;
|
|
|
|
|
if(header != null)
|
|
|
|
|
{
|
|
|
|
|
resultCell = header;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(resultCell == null)
|
|
|
|
|
{
|
|
|
|
|
resultCell = new TextCell { Text = model.GetSectionTitle(sectionIndex) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resultCell.Parent = _view;
|
|
|
|
|
return resultCell;
|
2016-08-18 06:57:14 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(position < size)
|
|
|
|
|
{
|
|
|
|
|
nextIsHeader = position == size - 1;
|
2016-08-21 07:50:48 +03:00
|
|
|
|
return (Cell)model.GetItem(sectionIndex, position - 1);
|
2016-08-18 06:57:14 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
position -= size;
|
|
|
|
|
}
|
2016-08-21 07:50:48 +03:00
|
|
|
|
|
|
|
|
|
return null;
|
2016-08-18 06:57:14 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-13 07:30:41 +03:00
|
|
|
|
}
|
|
|
|
|
}
|