I have a simple custom multiline element whose linebreak mode i've set to wordwrap, and lines property i set to 7. My text seems to wrap just fine, but the cell height stays the same, so the text extends the bounds of the cell. I've tried increasing the frame of the cell and overriding GetHeight, but it doesn't seem to work in either case. Also, it doesn't seem my GetHeight is even been called.
Any one face something similar? Or any ideas on what the issue might be?
public class DisclaimerMultilineElement : MultilineElement
{
public DisclaimerMultilineElement (string caption) : base(caption)
{
}
public DisclaimerMultilineElement (string caption, string value) : base(caption, value)
{
}
public DisclaimerMultilineElement (string caption, NSAction tapped) : base(caption, tapped)
{
}
public override float GetHeight (UITableView tableView, NSIndexPath indexPath)
{
var ht = base.GetHeight (tableView, indexPath);
//return base.GetHeight (tableView, indexPath);
return 400.0f;
}
public override UITableViewCell GetCell (MonoTouch.UIKit.UITableView tv)
{
UITableViewCell cell = base.GetCell (tv);
var frame = cell.Frame;
frame.Height = 300f;
//cell.Frame = new System.Drawing.RectangleF(frame.X, frame.Y, frame.Width, frame.Height);
cell.BackgroundColor = UIColor.Clear;
cell.TextLabel.Font = UIFont.BoldSystemFontOfSize (12);
cell.TextLabel.LineBreakMode = UILineBreakMode.WordWrap;
cell.TextLabel.Lines = 7;
cell.TextLabel.TextAlignment = UITextAlignment.Left;
cell.TextLabel.Text = Value;
return cell;
}
}
Make sure that UnevenRows is set to true in your Root element.
You need to override GetHeightForRow in your UITableViewSource and return the appropriate height.
Related
We've created a TableViewController so that a user can enable/disable different notification types. After the initial load, everything is fine until the user scrolls to the bottom then back to the top and the first 1-2 table view cells aren't displaying correctly.
Example:
https://imgur.com/7n2VpTo
Typically deleting and recreating the view controller and xib/cs files fixes this, but was wondering if any one knows the cause of this.
Controller Code:
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return 305;
}
public override nint NumberOfSections(UITableView tableView)
{
return 1;
}
public override nint RowsInSection(UITableView tableView, nint section)
{
return _numRows;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(Setting.Key) as Setting;
if (cell == null)
{
var values = _settings.Where(s => s.Index == indexPath.Row).FirstOrDefault();
cell = new Setting(values);
var views = NSBundle.MainBundle.LoadNib(Setting.Key, cell, null);
cell = Runtime.GetNSObject(views.ValueAt(0)) as Setting;
}
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
cell?.PopulateData(_settings.Where(s => s.Index == indexPath.Row).FirstOrDefault(), this);
return cell;
}
public override void ViewWillLayoutSubviews()
{
base.ViewWillLayoutSubviews();
}
Cell Code:
public partial class Setting : UITableViewCell
{
public static readonly NSString Key = new NSString("Setting");
public static readonly UINib Nib;
public SettingModel Values { get; set; }
static Setting()
{
Nib = UINib.FromName("Setting", NSBundle.MainBundle);
}
protected Setting(IntPtr handle) : base(handle) { }
public Setting() : base() {
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
}
public void PopulateData(SettingModel values)
{
//logic...
}
}
Upgrading to Visual Studio for Mac 8.6.5 resolved the issue.
I have Xamarin.iOS project, where is I use TableView
Here is tableView source code
public class ExperienceSourceNew: UITableViewSource
{
private UINavigationController primNav { get; set; }
private UITableView tableView { get; set; }
List<Experience> TableItems;
ExperienceViewControllerNew _owner;
static NSString cellIdentifier = new NSString("newcell_id");
public ExperienceSourceNew(List<Experience> items, ExperienceViewControllerNew owner, UINavigationController nav)
{
TableItems = items;
_owner = owner;
primNav = nav;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
if (TableItems.Count == 0)
{
var noDataLabel = new UILabel
{
Text = "No Experiences at your location at this time. Try to change destination",
TextColor = UIColor.Black,
TextAlignment = UITextAlignment.Center,
LineBreakMode = UILineBreakMode.WordWrap,
Lines = 0
};
tableview.BackgroundView = noDataLabel;
tableview.SeparatorStyle = UITableViewCellSeparatorStyle.None;
return TableItems.Count;
}
else
{
tableview.BackgroundView = null;
tableview.SeparatorStyle = UITableViewCellSeparatorStyle.SingleLine;
return TableItems.Count;
}
}
public override async void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var selectedExperience = await ExperienceMethods.GetSelectedTour(TableItems[indexPath.Row].id);
if (selectedExperience == "Saved")
{
ExperienceDetailViewController ExperienceDetailController = primNav.Storyboard.InstantiateViewController("ExperienceDetailViewController") as ExperienceDetailViewController;
primNav.PushViewController(ExperienceDetailController, true);
}
else
{
UIAlertController okAlertController = UIAlertController.Create("", "Cannot select this experience", UIAlertControllerStyle.Alert);
okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
}
tableView.DeselectRow(indexPath, true);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = (ExperienceCellNew)tableView.DequeueReusableCell(cellIdentifier, indexPath);
Experience item = TableItems[indexPath.Row];
cell.UpdateCell(item);
return cell;
}
I use custom Cell for TableView, so here is code for it
public ExperienceCellNew (IntPtr handle) : base (handle)
{
}
internal void UpdateCell(Experience experience)
{
var image_url = "https://xplorpal.com/" + experience.cover_image.img_path + "/150x150/" + experience.cover_image.img_file;
ExperienceTitleNew.Text = experience.title;
ExperiencePriceNew.Text = "$" + experience.price;
NSUrlSession session = NSUrlSession.SharedSession;
var dataTask = session.CreateDataTask(new NSUrlRequest(new NSUrl(image_url)), (data, response, error) =>
{
if (response != null)
{
DispatchQueue.MainQueue.DispatchAsync(() =>
{
ExperienceImageNew.Image = UIImage.LoadFromData(data);
});
}
});
dataTask.Resume();
}
}
My problem, that images not appears on View load, I have text in labels, but don't have images. If I scroll TableView, images are appears in cells.
Where can be problem and how to solve it?
Table Views with large number of rows display only a small fraction of their total items at a given time.It's efficient for table views to ask for only the cells for row that are being displayed Therefor on scrolling the table view, the cells get re-used and the data within the cell is repopulated.
Since you are using a downloaded image it appears to be slow.
You can try loading the image of the exact size as the image view within the cell.
This is similar to your issue
And also assigning the image to imageview on main thread and make it synchronous as UI changes require synchronous access to main thread.
As an alternative, you can use FFImageLoading which will let you do this
ImageService.LoadUrl(image_url).Into(ExperienceImageNew);
I want to add the default iOS footer to the tablesection in the tableview in Xamarin Forms. How can I go about doing this? I assume a customer renderer but I'm only reading that this can be done for Tableview?
To show an example, the following image is from Xcode storyboards when I enter the footer text on a static cell.
A Custom renderer is right, but you will have to use a custom renderer for the entire TableView. From there, you will need to override the TableViewModelRenderer and then the GetViewForFooter method in that ModelRenderer. Here's something that might help get you started:
public class FooterTableViewRenderer : TableViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged(e);
if (Control == null)
return;
var tableView = Control as UITableView;
var formsTableView = Element as TableView;
tableView.WeakDelegate = new CustomFooterTableViewModelRenderer (formsTableView);
}
private class CustomFooterTableViewModelRenderer : TableViewModelRenderer
{
public CustomFooterTableViewModelRenderer(TableView model) : base(model)
{
}
public override UIView GetViewForFooter(UITableView tableView, nint section)
{
return new UILabel()
{
Text = TitleForFooter(tableView, section), // or use some other text here
TextAlignment = UITextAlignment.Center
};
}
}
}
As mentioned in my comments below, you can alternatively override other methods in your TableViewModelRenderer:
public override nfloat GetHeightForFooter(UITableView tableView, nint section)
{
return 10;
}
public override string TitleForFooter(UITableView tableView, nint section)
{
return "This is the title for this given section";
}
I am trying to create a custom entry element using monotouch.dialog. I understand how to subclass a StringElement to style my own string elements - see example below:
public class CustomStyledStringElementPlain : MonoTouch.Dialog.StyledStringElement
{
public CustomStyledStringElementPlain (string _caption, UIColor _backgroundcolour, UITextAlignment _alignment) : base(string.Empty,string.Empty)
{
TextColor = UIColor.White;
Font = UIFont.FromName ("Helvetica-Bold", 14f);
Caption = _caption;
Alignment = _alignment;
BackgroundColor = _backgroundcolour;
}
}
However, when subclassing EntryElement, I am not able to access properties for the BackgroundColor for example (which is the main thing I want to change!) Here is what I have so far... Any pointers or advice on how I could change the background color or otherwise style entry elements would be much appreciated!
public class CustomStyledEntryElementPlain : MonoTouch.Dialog.EntryElement
{
public CustomStyledEntryElementPlain (string _caption, UIColor _colour, UITextAlignment _alignment) : base(string.Empty,string.Empty)
{
ReturnKeyType = UIReturnKeyType.Done;
Caption = _caption;
}
}
To customize a MonoTouch.Dialog Element, you can override the GetCell method and set the appearance you want on the cell object. Something like this:
public override UITableViewCell GetCell(UITableView tableView) {
var cell = base.GetCell(tableView);
cell.BackgroundColor = _colour;
return cell;
}
I have the following code set up:
TableView = new UITableView();
TableView.Source = new DataSource();
m_MainScroll.Add(view); // scrollview area
TableView.ReloadData ();
DataSource is simple:
class DataSource : UITableViewSource {
public DataSource ()
{
}
public override int NumberOfSections (UITableView tableView)
{
return 1;
}
public override int RowsInSection (UITableView tableview, int section)
{
return 10;
}
// Customize the appearance of table view cells.
public override UITableViewCell GetCell (UITableView tableView, MonoTouch.Foundation.NSIndexPath indexPath)
{
return new UITableViewCell();
}
}
Basically GetCell is never called and I never see the table show up anyway.
Any ideas why?
edit:
Some more potentially relevant code:
(in ViewDidLoad):
m_MainScroll = new UIScrollView(new RectangleF(0, 0, 320, 372));
m_MainScroll.ContentSize = new SizeF(300, ScrollerHeight);
m_MainScroll.ShowsVerticalScrollIndicator = true;
m_MainScroll.DraggingStarted += DragStarted;
AddComponent(m_MainScroll);
UIToolbar bar = new UIToolbar(new RectangleF(0, 372, 320, 44));
View.Add(bar);
UIBarButtonItem barBut = new UIBarButtonItem();
barBut.Style = UIBarButtonItemStyle.Bordered;
barBut.Title = "Next";
NextButton = barBut;
UIBarButtonItem flexer = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
UIBarButtonItem []items = new UIBarButtonItem[2];
items[0] = flexer;
items[1] = barBut;
bar.Items = items;
AddComponent(bar);
public void AddComponent(UIView view)
{
m_Components.Add(view);
View.Add(view);
}
Where m_Components is just a list of UIView and is really only used to defocus controls which have the keyboard on.