How to fix UICollectionView - All cells disappear - Xamarin ios - xamarin.ios

I am using a UICollectionView in C# Xamarin ios and sometimes all of the cells will disappear from the screen. This happens normally on a scroll and I have to re-invoke the view that my UICollection View is on.
I can't show my exact code as this is a project that I am working on but the initialization basics look a little like this:
Bounds screenBounds = screen.Bounds
UICollectionViewFlowLayout layout = new UICollectionViewFlowLayout();
UICollectionView collectionView = new UICollectionView(layout, bounds)
I initialize a few other things like source and register cell and also add separation and border styles.
I have been also getting an error about a view not being in the hierarchy don't know if this has anything to do with it.
I do return the collectionView at the end and will add this returned value to my template which has a scroll view in which I add the UICollectionView to.
May I also mention I don't use any of the StoryBoard and am using a DuqueReusable cell in my collection view source.
I have been stuck on this for ages so thank you in advance for anyone who can give me any sort of tips or answers to this question.

Insure you make any changes to ItemsSource or to cells data on UI thread only, otherwise you might obtains an uncatchanble async crash and you'll end up with an empty view.
Device.BeginInvokeOnMainThread(() => {
// do your stuff
});

Related

ScrollingView editable in height Xamarin.ios

I have been trying to create a ScrollingView on Xamarin.ios for several days now which shrinks and enlarges when I establish it, showing a larger scrollable part and hiding the empty part if necessary. I'm trying to handle it like this:
ScrollView.ContentSize = new CGSize(View.Bounds.Width, ViewBackground.Bounds.Height - (StackEsercizio.Bounds.Height * 1));
This statement works partially, only when placed in the ViewDidAppear and only for the first time. Do you have any advice or solution?
Finally, I solved it on my own. For the growth of the community, place the solution on github at this link: https://github.com/aleledda98/MyfitnessApp/blob/master/CreaSchedaNew.cs
the scrolling view moves dynamically based on the number of letters entered on a specific UITextField, thanks to all the same <3

How do you use a storyboard reference in a Tab Bar Controller with Visual Studio?

I have a view controller in one storyboard that I'd like to reuse in another storyboard's Tab Bar Controller. In XCode, I can add a storyboard reference and then ctrl-drag from the Tab Bar Controller to it, and it shows up as another tab, just like a View Controller would in the same storyboard. I'm trying to do this in VS 2017 though and it doesn't seem to work. Or if it does, I'm unsure of how to do it. I tried adding a storyboard reference and ctrl-dragging, just like I do for normal View Controllers. I select "Tab" under "View Relationship" which pops up when I finish dragging, but it never makes the link and never makes the tab.
Is this even something that is valid? And if it is, is it a bug/limitation with VS that I can't do this, and is there a workaround?
Edit:
I managed to get this to work programmatically. Here's what I did in case anyone wants to know. However, I still would like to know the answer to my previous questions.
First, in your desired VC (I'm going to call it TestVC), make sure you add a Tab Bar Item (not a tab bar). Set up the title and image as you would normally. Then, in your Tab Bar Controller's ViewDidLoad method, do something like this:
var storyboard = UIStoryboard.FromName("StoryboardNameTestVCIsIn", null);
var vc = storyboard.InstantiateViewController("TestVC");
var existing = new List<UIViewController>(ViewControllers);
existing.Add(vc);
ViewControllers = existing.ToArray();
Is this even something that is valid? And if it is, is it a bug/limitation with VS that I can't do this, and is there a workaround?
It is not support to add Tab relationship by this way. As you mentioned above, you could only implement that programmatically. Maybe in the near future Xamarin will support it like in Xcode.
Click on the segue , and you can see all the actions you can do.

UILabel not wrapping in UITableView until device rotate (iOS8)

I have a custom MvxTableViewCell that is associated with an MvxStandardTableViewSource. That Source is then applied to a UITableView. The custom table cell is defined without any Storyboard or NIB. It is laid out in code and uses AutoLayout.
this.searchResultsTable = new UITableView();
this.searchResultsTable.AccessibilityIdentifier = "SearchView_SearchResultsTable";
this.searchResultsTable.TranslatesAutoresizingMaskIntoConstraints = false;
this.searchResultsTable.RowHeight = UITableView.AutomaticDimension;
this.searchResultsTable.EstimatedRowHeight = 44.0f;
this.searchResultsTable.RegisterClassForCellReuse(typeof(CustomerItemCell), new NSString("CustomerItemCell"));
this.searchResultsTable.AllowsMultipleSelectionDuringEditing = true;
this.searchResultsTable.TableFooterView = new UIView();
this.searchResultsTableDataSource = new MvxStandardTableViewSource(this.searchResultsTable, new NSString("CustomerItemCell"));
this.searchResultsTable.Source = this.searchResultsTableDataSource;
The MVxStandardTableViewSource is databound to a ViewModel property of type List
var set = this.CreateBindingSet<SearchView, SearchViewModel>();
set.Bind(this.searchResultsTableDataSource).To(vm => vm.SearchResults);
set.Bind(this.searchBar).For(x => x.Text).To(vm => vm.CurrentSearchCriteria);
set.Apply();
This all works fine until an item in the data source causes some text wrapping in one of the UILabels and consequently a different height to the other cells.
The cell height is mostly correctly calculated but the UILabel within the
cell does not get redrawn until the device is rotated. I am using iOS AutoLayout to layout the various UIViews in the Cell.
Here are some examples of the large cell in my layout, see the
person "THISISAPATIENTWITHA-" (note this is test data not real people's data)
Initial display of cells
Same cells but device has been rotated
Still the same cells with device rotated back to original
How do I get the UILabel to redraw? We only need to support iOS8 and above.
I cannot see an event or method that gets called when the data binding has happened that would allow me to effectively tell the custom cell "You now have your subviews populated with bound data so redraw them"
The table has another issue too that is covered by this question, Implementing cell reuse for varying height cells in UITableView
Simple Repro on Github
https://github.com/munkii/TableCellResizeIssue
UPDATE:
I've forked your GitHub project and submitted a pull request. But here's my updates to your project.
https://github.com/SharpMobileCode/TableCellResizeIssue
First, you're using FluentLayout for your constraints. Nothing wrong with that actually, but that's some good info to tell others. :)
Second, in order for UITableView.AutomaticDimension to work on TableView Cells, there must be enough autolayout constraints defined in order for the cell to calculate the height of the cell. UITableView.AutomaticDimension depends on proper AutoLayout constraints.
Since you were using FluentLayout to abstract iOS AutoLayout constraints, this was not obvious as no warnings were present in the application output window. Though FluentLayout was technically correct, it however wasn't enough for UITableView.AutomaticDimension to automatically calculate each cell height.
So what I did was added a few more constraints. Look in CustomerItemCell.CreateView() in the pull request (or my github link). You can see that I added additional constraints for all the bottom labels so that they add a Bottom Constraint to the ContentView (Just like you did with this.bornLabel). This had to be applied to all the labels on the bottom of the cell. This gives AutoLayout enough information to properly calculate the cell height.
Third, This almost works, but if you rotate to Landscape, you'll notice that the long name cells will be bigger and have extra padding. To fix this, I created another class called AutoLayoutLabel that inherits from UILabel. I overrode the Bounds property so that it changes the PreferredMaxLayoutWidth to the proper width when rotated to Landscape, and back to Portrait. You then will need to use AutoLayoutLabel instead of UILabel. You'll need this for all labels that need to wrap. I'm not sure how to set PreferredMaxLayoutWidth to auto in code, but this is how to do it programmatically (which also works for iOS 7).
public class AutoLayoutLabel : UILabel
{
public override CGRect Bounds
{
get
{
return base.Bounds;
}
set
{
base.Bounds = value;
if(this.Lines == 0 && Bounds.Size.Width != PreferredMaxLayoutWidth)
{
PreferredMaxLayoutWidth = Bounds.Size.Width;
SetNeedsUpdateConstraints();
}
}
}
}
Well, that should do it!
I now have a solution to this part of my issue. Prompted by #SharpMobileCode reference to PreferredMaxLayoutWidth I decided to give that another go. Rather that setting it to Automatic (which seems impossible in code) I am setting it Explicitly, once AutoLayout has done its thing. Like this
/// <summary>
/// Lays out subviews.
/// </summary>
public override void LayoutSubviews()
{
base.LayoutSubviews();
this.nameLabel.PreferredMaxLayoutWidth = this.nameLabel.Frame.Size.Width;
}
I am no longer seeing the Labels not wrap (hurrah!) however I am seeing an issue with what looks like cell reuse. Once I scroll all of the cell off the top of the screen I can scroll it back on and it has reverted to the same height as all the other cells. I can see the label is still wrapping but the cell height is wrong.
The standard table views in MvvmCross date back to iOS4 - while the new UITableViewAutomaticDimension sizing wasn't really added until much more recently (iOS8?)
Most real apps tend to use custom cells rather than the standard ones, but if you do want to use the standard ones, then I'd guess you could try adding some code to the setters in the cell which would trigger resize recalculations - e.g. to setters in https://github.com/MvvmCross/MvvmCross/blob/3.5/Cirrious/Cirrious.MvvmCross.Binding.Touch/Views/MvxStandardTableViewCell.cs#L73
I would guess that judiciously placed calls in there to request layout recalc would cause the parent cell and table to redraw.

How to show header of ListView when its empty

I am developing the following screen
The fourboxes next to each other are buttons. On clicking of the buttons I am changing the adapter of the listview.
Since the content above the listview took up lot of space I made the whole thing as an header and added it via code.
myPollsList = (ListView) findViewById(R.id.listArea);
myPollsList.addHeaderView(getLayoutInflater().inflate(R.layout.profile_listview_header, null));
Now I want to show some view when the list is empty. But if I do that then the header also goes away.
I am using this in a Activity and not a ListActivity. Any suggestions or workarounds for showing the header even when the list is empty ?
EDIT: Refer to my earlier question here ListView not getting space to show content on smaller screens . This is where someone suggested me to solve the problem by putting it as a header
I found a simple solution for this problem. If there's no elements for list and you are not adding the adapter, just add this:
mListView.setAdapter(null);
and the header will appear. It's easier than adding empty / fake item to the list.
So this is how I solved it. I had a custom adapter which was connected to the listview. When it found that it had zero items to display. It would add a fake empty view as an item to the list.
maybe you will like this Android addHeaderView disappears when no items in ListView
override/subclass your adapter to return false from isEmpty()
Don't use top layouts of button as header for list view.
So to adjust UI without using list header use weights.
Give parent Linear layout weight sum as 4 and 1, 1 to top Layouts and 2 for list view.

Why isn't MvxStandardTableViewSource SelectedItem updating properly?

I'm trying to bind a UITableView to an ObservableCollection<MyTypeViewModel> using MvxStandardTableViewSource, and I'm getting weird behavior and bindings that aren't working
The (partial) code is this:
tblFeatures = new UITableView ();
mSource = new MvxStandardTableViewSource(tblFeatures, "TitleText Name");
var set = this.CreateBindingSet<MyTypeView, MyTypeViewModel> ();
set.Bind(mSource).To (vm => vm.Objects);
set.Bind(mSource).For(s => s.SelectedItem).To (vm => vm.SelectedObject);
set.Apply ();
What I'm seeing is that when I select an item in the table, it does update SelectedObject with the new value. But when I change SelectedObject by some other means, the table does not update the displayed selected item. I have verified that the SelectedObject really is being changed, by setting a breakpoint and by binding another control to it; the other control (a label) does change as the selection changes, but the UITableView does not.
Am I doing something wrong, or could this be an issue in MVVMCross?
The selecteditem binding was requested as a 'nice to have' and was mainly requested for the user story where a user clicks on a list item - so this is currently a 'one way to source' implementation.
The very basic details and some code can be found via - https://github.com/slodge/MvvmCross/issues/278
In truth, the current binding is abusing the 'selected' paradigm - as it doesn't really reflect the selection state of the cell and also has no handling of mutiselect - instead it just lets the viewmodel know the latest tapped item.
If there are genuine user stories/requirements for full two'way binding, then these should be addable - eg if the user story were for scrolling the item into view then 'scrollToRowAt' could be used - see How to scroll UITableView to specific position - but this again might not be true 'selection' within the uitableview.
if you wanted to implement this yourself it should be fairly straight-forward to override the binding with your own one (see the custom binding n+1 in http://mvvmcross.wordpress.com for an intro on custom bindings).
could this be an issue in MVVMCross?
Overall I think I'd categorise it as a known limitation of that particular binding caused by lack of user demand and by some confusion over whether selection genuinely means selection in the touch screen era.
if it was logged as a bug I'd say it wasn't.. If it was logged ss a feature request I'd try getting as much user input as i could about what devs really want from this, whether they want true cell selection or scroll into view, both or something more.
By other means you mean not from UI thread I presume. Please try by invoking the change on UI thread.

Resources