adding a page control to UITableView - uitableview

I have a UITableView that we're looking to adjust to have a carousel-like effect to items in our table that the user has pinned to the top.
I see that the page control is a view controller and the other item is just the dot container. I've seen a few other SO answers suggest I use a UIScrollview with the page control but in all those cases their data was just images and in my case it's a combination of text, buttons, and images so I'm lost on what a good clean solution would be.

As I mentioned in the comment , we can't just combine TabView + PageControl, ScrollView is also needed in this scenario .
Create a ScrollView to wrap all the views/elements ,and put the ScrollView into Cell.ContentView.
Add PageControl into Cell.ContentView.
Refer to
UIScrollView and UIPageControl within UITableView
UIPageControl with UITableView
Update
Is the following screen shot you want ?
Sample code
public class User
{
public string icon { get; set; }
public string name { get; set; }
public string content { get; set; }
public string image { get; set; }
}
[Register("UIViewController1")]
public class UIViewController1 : UIViewController
{
public UIViewController1()
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
UITableView table = new UITableView(View.Bounds); // defaults to Plain style
List<User> tableItems = new List<User>();
tableItems.Add(new User { icon = "dog.png", name = "Cole", content = "I'm test1", image = "bg1.PNG" });
tableItems.Add(new User { icon = "dog.png", name = "Kevin", content = "I'm test222222222", image = "bg2.PNG" });
tableItems.Add(new User { icon = "dog.png", name = "Tom", content = "I'm test333333_33333333", image = "bg3.PNG" });
table.Source = new TableSource(tableItems);
Add(table);
}
}
public class TableSource : UITableViewSource
{
List<User> TableItems;
string CellIdentifier = "TableCell";
public TableSource(List<User> items)
{
TableItems = items;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return TableItems.Count;
}
int CellHeight = 250;
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
return CellHeight;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
User item = TableItems[indexPath.Row];
//if there are no cells to reuse, create a new one
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
UIScrollView sc = new UIScrollView();
sc.Frame = new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, CellHeight-10);
for (int i = 0; i < 10; i++)
{
UIImageView image = new UIImageView();
image.Frame = new CGRect(i* UIScreen.MainScreen.Bounds.Width + 20, 10, 50, 50);
image.Layer.MasksToBounds = true;
image.Layer.CornerRadius = 25;
image.Image = UIImage.FromFile(item.icon);
sc.Add(image);
UILabel label = new UILabel();
label.Frame = new CGRect(i * UIScreen.MainScreen.Bounds.Width+80, 10, 100, 50);
label.TextColor = UIColor.LightGray;
label.Text = item.name;
sc.Add(label);
UILabel label2 = new UILabel();
label2.Frame = new CGRect(i * UIScreen.MainScreen.Bounds.Width +20, 60, 300, 60);
label2.Text = item.content;
sc.Add(label2);
UIImageView image2 = new UIImageView();
image2.Frame = new CGRect(i * UIScreen.MainScreen.Bounds.Width + 100, 130, 150, 100);
image2.Image = UIImage.FromFile(item.image);
sc.Add(image2);
}
sc.ContentSize = new CGSize(10 * UIScreen.MainScreen.Bounds.Width, CellHeight-10);
sc.PagingEnabled = true;
sc.ShowsHorizontalScrollIndicator = false;
UIPageControl page = new UIPageControl();
page.BackgroundColor = UIColor.Red;
page.Frame = new CGRect(0, CellHeight-10, cell.ContentView.Frame.Width, 10);
page.Pages = 10;
page.CurrentPage = 0;
cell.ContentView.Add(sc);
cell.ContentView.Add(page);
sc.Scrolled += (object sender, EventArgs e) => {
var pageWidth = sc.Frame.Size.Width;
var fractionalPage = sc.ContentOffset.X / pageWidth;
var p = Math.Floor(fractionalPage);
page.CurrentPage = (int)p;
};
}
return cell;
}
}

Related

Overriding Back button navigation in Xamarin.IOS

I am trying to override the default back button behaviour of IOS, using Xamarin.IOS framework.
I have a stack of objects inside my ViewController, my requirement is that when the user presses back to navigate to previous ViewController, i will navigate only when my stack is empty otherwise i will stay in that screen(ViewController).
For this i tried several thing, like overriding the ViewWillDisappear and setting the PopViewController to false but i am unable to do this. Please guide.
public override void ViewWillDisappear(bool animated)
{
Stack<Object> st = vPage.uContentStack;
if (st.Count != 0)
{
Object pop_obj = st.Pop();
if (st.Count != 0)
{
NavigationController.PopViewController(false);// Here trying to stop navigating back
Object peek_obj = st.Peek();
vPage.ContentUpdateOnBackPress(pop_obj, peek_obj);
}
else
{
NavigationController.PopViewController(true);
}
}
else
{
NavigationController.PopViewController(true);
}
base.ViewWillDisappear(animated);
}
You could customize the Navigation Bar in the specific ViewController
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
NavigationController.NavigationBar.Hidden = true;
double height = IsiphoneX();
UIView backView = new UIView()
{
BackgroundColor = UIColor.White,
Frame = new CGRect(0, 20, UIScreen.MainScreen.Bounds.Width, height),
};
UIButton backBtn = new UIButton()
{
Frame = new CGRect(20, height - 44, 40, 44),
Font = UIFont.SystemFontOfSize(18),
};
backBtn.SetTitle("<", UIControlState.Normal);
// backBtn.SetBackgroundImage(UIImage.FromBundle("xx.png"),UIControlState.Normal); or you can set image here
backBtn.SetTitleColor(UIColor.FromRGB(60,140,250), UIControlState.Normal);
backBtn.AddTarget(this, new Selector("GoBack"), UIControlEvent.TouchUpInside);
UILabel titleLabel = new UILabel()
{
Frame = new CGRect(UIScreen.MainScreen.Bounds.Width / 2 - 75, 0, 150, height),
Font = UIFont.SystemFontOfSize(20),
Text = "xxx",
TextAlignment = UITextAlignment.Center,
TextColor = UIColor.Black,
Lines = 0,
};
UILabel line = new UILabel()
{
Frame = new CGRect(0, height, UIScreen.MainScreen.Bounds.Width, 0.5),
BackgroundColor = UIColor.Black,
};
backView.AddSubview(backBtn);
backView.AddSubview(titleLabel);
backView.AddSubview(line);
View.AddSubview(backView);
}
double IsiphoneX()
{
double height = 44;
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if (UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 64;
}
}
return height;
}
[Export("GoBack")]
void GoBack()
{
//handle logic here
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NavigationController.NavigationBar.Hidden = false;
}
In this solution you could set the style of the navigation bar , like text color of title or icon of back button .

Xamarin UICollectionView some cells disappear after scrolling down and back

I have a problem with UICollectionView, exactly with cells... When I'm scrolling down and back so some cells are just empty. They just disappear something like this:
My ViewDidLoad() in OrdersView:
public override void ViewDidLoad()
{
Title = "My Orders..";
base.ViewDidLoad();
ordersCollectionView.Frame = new CGRect(ordersCollectionView.Frame.X, ordersCollectionView.Frame.Y, ordersCollectionView.Frame.Width, ordersCollectionView.Frame.Height);
ordersCollectionView.ScrollEnabled = true;
var layout = new UICollectionViewFlowLayout
{
ItemSize = new CGSize() { Width = ordersCollectionView.Bounds.Width, Height = 80 },
MinimumInteritemSpacing = 0,
MinimumLineSpacing = 2,
ScrollDirection = UICollectionViewScrollDirection.Vertical
};
ordersCollectionView.SetCollectionViewLayout(layout, true);
this.ClearBindings(_source);
_source = new OrdersCollectionViewSource(ordersCollectionView);
this.AddBindings(new Dictionary<object, string>
{
{ _source, "ItemsSource Orders; SelectedItem SelectedOrder; SelectionChangedCommand ShowOrderDetailCommand" }
});
ordersCollectionView.Source = _source;
ordersCollectionView.ReloadData();
Mvx.Resolve<IMvxMessenger>().SubscribeOnMainThread<OrdersLoadedMessage>(mess =>
{
this.ClearBindings(_source);
_source = new OrdersCollectionViewSource(ordersCollectionView);
this.AddBindings(new Dictionary<object, string>
{
{ _source, "ItemsSource Orders; SelectedItem SelectedOrder; SelectionChangedCommand ShowOrderDetailCommand" }
});
ordersCollectionView.Source = _source;
ordersCollectionView.ReloadData();
}, MvxReference.Strong);
InitializeRefreshControl();
ViewMessages.ViewCreatedMessages(this, "OrdersView", ViewModel);
}
OrdersCollectionViewSource:
public class OrdersCollectionViewSource : MvxCollectionViewSource
{
private static readonly NSString CellIdentifier = new NSString("OrdersCollectionViewCell");
public OrdersCollectionViewSource(UICollectionView collectionView) : base(collectionView)
{
collectionView.RegisterClassForCell(typeof(OrdersCollectionViewCell), CellIdentifier);
}
protected override UICollectionViewCell GetOrCreateCellFor(UICollectionView collectionView, NSIndexPath indexPath, object item)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellIdentifier, indexPath);
cell.BackgroundColor = UIColor.FromRGB(237, 237, 237);
return cell;
}
}
OrdersCollectionViewCell:
public class OrdersCollectionViewCell : MvxCollectionViewCell
{
[Export("initWithFrame:")]
public OrdersCollectionViewCell(CGRect frame) : base(frame)
{
Layer.BackgroundColor = new CGColor(220, 25, 25, 255);
//left
var labelName = new UILabel();
labelName.Frame = new CGRect(10f, 15f, (float)(Bounds.Width / 2 + 20), 20f);
labelName.Font = UIFont.PreferredHeadline;
labelName.TextColor = UIColor.FromRGBA(90, 24, 24, 255);
labelName.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
labelName.Text = "Text";
var labelPickupDate = new UILabel();
labelPickupDate.Frame = new CGRect(10f, 45f, (float)(Bounds.Width / 2 - 10), 20f);
labelPickupDate.Font = UIFont.PreferredBody;
labelPickupDate.TextColor = UIColor.Black;
labelPickupDate.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
//right
var labelPrice = new UILabel();
labelPrice.Frame = new CGRect((float)(Bounds.Width / 2), 45f, (float)(Bounds.Width / 2 - 10), 20f);
labelPrice.TextAlignment = UITextAlignment.Right;
labelPrice.Font = UIFont.PreferredBody;
labelPrice.TextColor = UIColor.Black;
labelPrice.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
var labelStatus = new UILabel();
labelStatus.Frame = new CGRect((float)(Bounds.Width / 2), 15f, (float)(Bounds.Width / 2 - 10f), 20f);
labelStatus.TextAlignment = UITextAlignment.Right;
labelStatus.Font = UIFont.PreferredHeadline;
labelStatus.TextColor = UIColor.FromRGBA(15, 113, 10, 255);
labelStatus.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin;
Add(labelName);
Add(labelPickupDate);
Add(labelStatus);
Add(labelPrice);
this.DelayBind(() =>
{
var set = this.CreateBindingSet<OrdersCollectionViewCell, Order>();
set.Bind(labelPickupDate).For(q => q.Text).To(vm => vm.PickupDate).WithConversion("StringDateTimeConverter");
set.Bind(labelStatus).For(q => q.Text).To(vm => vm.OrderStatus);
set.Bind(labelPrice).To(vm => vm.Sum).WithConversion("CreditConverter");
set.Apply();
});
}
}
I found here some similarly problems but everything in xcode.. so I tried something but it still doesn't work well.
EDIT - MY SOLUTION:
protected override UICollectionViewCell GetOrCreateCellFor(UICollectionView collectionView, NSIndexPath indexPath, object item)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellIdentifier, indexPath);
cell.BackgroundColor = UIColor.FromRGB(237, 237, 237);
var order = (Order) item;
var test = (OrdersCollectionViewCell) cell;
test.labelName.Text = "Name";
test.labelPickupDate.Text = StringConvertor.StringDateTime(order.PickupDate);
test.labelPrice.Text = StringConvertor.PriceConvertor(order.Sum);
test.labelStatus.Text = order.OrderStatus;
return test;
}
I had a very similar problem. It is because your table reuses cells. dequeueReusableCellWithIdentifier will reuse the same cell references when scrolling and it may not preserve the text you intended to display.
Your GetOrCreateCellFor function contains a call to DequeueReusableCell. You should also set the cell's text within this function (e.g. cell.labelName.text = "my text here").
protected override UICollectionViewCell GetOrCreateCellFor(UICollectionView collectionView, NSIndexPath indexPath, object item)
{
var cell = (UICollectionViewCell)collectionView.DequeueReusableCell(CellIdentifier, indexPath);
cell.BackgroundColor = UIColor.FromRGB(237, 237, 237);
cell.labelName.text = "Your label here"
cell.labelPickupDate.text = "Your pickup date here"
cell.labelPrice.text = "Your price here"
cell.labelStatus.text = "Your status here"
return cell;
}
Please see this answer below for the full explanation. Let me know if you have any questions.
https://stackoverflow.com/a/43164656/2179970

Using FFImageLoading Synchronously?

I need to use the LoadUrl method of the FFImageLoading ImageService class synchronously since it is called in a CreateCell method of a data source for a grid. Using Xamarin.iOS and c#. Appreciate a quick solution. Here is the current code:
public override IGFlowLayoutViewCell CreateCell(IGFlowLayoutView flowLayoutView, nint index)
{
IGFlowLayoutViewCell cell = flowLayoutView.DequeueReusableCell("CELL") as IGFlowLayoutViewCell;
UIImageView iconImage = new UIImageView();
if (cell == null)
{
cell = new IGFlowLayoutViewCell("CELL");
cell.ContentInset = new UIEdgeInsets(2, 2, 2, 2);
cell.ContentMode = UIViewContentMode.Center;
cell.Layer.BorderColor = UIColor.LightGray.CGColor;
cell.Layer.BorderWidth = 1;
cell.ContentView = iconImage;
ImageService.LoadUrl(instrumentImageUrls[index], new TimeSpan(12, 0, 0))
.Into((UIImageView)cell.ContentView,0);
}
return cell;
}
public override IGFlowLayoutViewCell CreateCell(IGFlowLayoutView flowLayoutView, nint index)
{
IGFlowLayoutViewCell cell = flowLayoutView.DequeueReusableCell("CELL") as IGFlowLayoutViewCell;
UIImageView iconImage = new UIImageView();
if (cell == null)
{
cell = new IGFlowLayoutViewCell("CELL");
cell.ContentInset = new UIEdgeInsets(2, 2, 2, 2);
cell.ContentMode = UIViewContentMode.Center;
cell.Layer.BorderColor = UIColor.LightGray.CGColor;
cell.Layer.BorderWidth = 1;
cell.ContentView = iconImage;
ImageService.LoadUrl(instrumentImageUrls[index], new TimeSpan(12, 0, 0))
.IntoAsync((UIImageView)cell.ContentView,0).GetAwaiter().GetResult();
}
return cell;
}

UITableView UITableViewCellStyle.Value1 TextLabel is overlapping the DetailTextLabel

I'm using Xamarin iOS and on iOS 9.2 devices the UITableView cells with cell style of UITableViewCellStyle.Value1 have the TextLabel overlapping the DetailTextLabel.
This doesn't happen on iOS 8. Anybody know what I can do to fix it without rolling my own cell? I just would like the TextLabel to ellipsis instead of overlapping the DetailTextLabel.
I couldn't find a fix. A blank project reproduced it with just a simple TableView so I rolled my own custom cell.
public class CustomTableViewCell : UITableViewCell
{
UILabel headingLabel, subheadingLabel;
public MTableViewCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Default;
headingLabel = new UILabel ();
subheadingLabel = new UILabel () {
TextColor = UIColor.Gray,
TextAlignment = UITextAlignment.Center
};
ContentView.AddSubviews (new UIView[] { headingLabel, subheadingLabel });
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
headingLabel.Frame = new CGRect (15, 0, ContentView.Bounds.Width - 130, ContentView.Bounds.Height);
subheadingLabel.Frame = new CGRect (ContentView.Bounds.Width - 110, 0, 95, ContentView.Bounds.Height);
}
public override UILabel TextLabel {
get {
return headingLabel;
}
}
public override UILabel DetailTextLabel {
get {
return subheadingLabel;
}
}
}
Pasudocode to decide if you want to dequeue value1 or sub type of cell
public static func isVerticalLayout(primary: String, secondary: NSAttributedString,
liveHostView: UIView) -> Bool
{
let csWidth = liveHostView.bounds.width
let headingLabel = UILabel()
let subheadingLabel = UILabel()
headingLabel.text = primary
headingLabel.numberOfLines = 0
headingLabel.lineBreakMode = .byWordWrapping
subheadingLabel.attributedText = secondary
subheadingLabel.textAlignment = .right
subheadingLabel.numberOfLines = 1
subheadingLabel.lineBreakMode = .byWordWrapping
let clipw = csWidth - P97GEL.Constants.leftTextMargin - P97GEL.Constants.rightTextMargin
let bounds = CGRect(x: 0, y: 0, width: clipw, height: CGFloat.greatestFiniteMagnitude)
let psRect = headingLabel.textRect(forBounds: bounds, limitedToNumberOfLines: 1)
let ps = psRect.size
let ssRect = subheadingLabel.textRect(forBounds: bounds, limitedToNumberOfLines: 1)
let ss = ssRect.size
headingLabel.frame.origin = CGPoint(x: P97GEL.Constants.leftTextMargin, y: P97GEL.Constants.verticalMargin)
headingLabel.frame.size = ps
subheadingLabel.frame.size = ss
if csWidth >= ps.width + ss.width + (3 * P97GEL.Constants.horizontalMargin) {
return false
} else {
return true
}
}

resize cell in xamarin

I have a table view built in Xamarin that is populated with some addresses, but i can't figure out how to resize the cell so that all information will fit.
My TableViewCell Class:
using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.CodeDom.Compiler;
using System.Drawing;
namespace Vipar
{
public class CustomVegeeeCell : UITableViewCell {
UILabel Title, Addr, CityState;
//UIImageView imageView;
public CustomVegeeeCell (NSString cellId) : base (UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.Clear;//(84, 84, 85);
//imageView = new UIImageView();
Title = new UILabel () {
Font = UIFont.FromName("Arial-BoldMT", 16f),
TextColor = UIColor.Black,
BackgroundColor = UIColor.Clear
};
Addr = new UILabel () {
Font = UIFont.FromName("ArialMT", 12f),
TextColor = UIColor.Black,
//TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
CityState = new UILabel () {
Font = UIFont.FromName("ArialMT", 12f),
TextColor = UIColor.Black,
//TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.Add (Title);
ContentView.Add (Addr);
ContentView.Add (CityState);
}
public void UpdateCell (string caption, string subtitle, string subtitle1)//, UIImage image)
{
//imageView.Image = image;
Title.Text = caption;
Addr.Text = subtitle;
CityState.Text = subtitle1;
}
public override void LayoutSubviews ()
{
base.LayoutSubviews ();
//imageView.Frame = new RectangleF(ContentView.Bounds.Width - 63, 5, 33, 33);
Title.Frame = new RectangleF(5, 4, ContentView.Bounds.Width - 63, 25);
Addr.Frame = new RectangleF(5, 18, ContentView.Bounds.Width - 63, 25);
CityState.Frame = new RectangleF(5, 30, ContentView.Bounds.Width - 63, 25);
}
}
}
In UITableViewSource, you need to override GetHeightForRow:
public override float GetHeightForRow(UITableView tableView, NSIndexPath indexPath)

Resources