I've got a UITableView located in a View attached to a SlidingPanel.
I'm using SlidingPanels.Lib, and I've got a custom presenter
Here's a gist of the custom presenter
From there my MenuView is really straight forward.
public class MenuView : ViewControllerBase
{
private new MenuViewModel ViewModel { get { return (MenuViewModel)base.ViewModel; } }
public override void ViewDidLoad()
{
base.ViewDidLoad();
// todo: this should actually be...
// _currentBookId = currentUser.UserBooks[0].BookId;
// _homeViewModel.ChapterViewModel = Mvx.Resolve<IChapterService>().FindByBookId(_currentBookId);
ViewModel.Chapters = Mvx.Resolve<IChapterService>().Find();
// this ensures the sliding panel doesn't fill the entire view.
var frame = View.Frame;
frame.Width = 300;
View.Frame = frame;
// var currentUser = Mvx.Resolve<IUserService>().GetById(Mvx.Resolve<UserModel>().Id);
var label = new UILabel(new RectangleF(10, 10, 300, 40))
{
TextColor = UIColor.White,
};
Add(label);
//var listHeight = (chapters.Count*40);
var navigationList = new UITableView(new RectangleF(0, 50, 300, 300))
{
Source = new NavigationTableSource(ViewModel.Chapters)
};
Add(navigationList);
var set = this.CreateBindingSet<MenuView, MenuViewModel>();
set.Bind(label).To(vm => vm.DisplayName);
set.Apply();
}
}
Unfortunately I'm not sure where to look in order to allow the TableView to scroll. I can see it, but it goes beyond the bottom of the screen.
I think the problem is in:
var listHeight = (chapters.Count*40);
Instead of this, try setting the height to the height of the available screen (which depends on which iPhone/iPad you are on). After this, then the list will scroll within that available height.
Took a couple of hours of dicking around to discover that the original source code that I grabbed from #patbonecrusher's Github repo had some differences from the lib that you can find at #fcaico's Github repo
Long story short... all I had to do was compile #fcaico's version and deploy it into my app, and the scrolling came back. Now I realize that #fcaico's repo just contains a submodule to #patbonecrusher's, but for some reason... the recompile fixed the issue. Don't have a lot of time to dig into the reason why.
Related
Context: I want to achieve something similar with How can I mimic the bottom sheet from the Maps app? based on https://github.com/grendio/XBottomSheet/tree/master/XBottomSheet.Samples/XBottomSheet.Touch
Problem: If I use the BottomSheet with Google Maps for iOS View it does not let me to drag up or down the BottomSheet, even if it adds (it's visible on the screen).
Code: As already mentioned I have a Google Maps View and my BottomSheet View:
public override void ViewDidLoad()
{
base.ViewDidLoad();
SetMap();
SetBottomSheet();
}
private void SetMap()
{
var frame = new CGRect(0, View.Frame.GetMaxY(), View.Frame.Width, View.Frame.Height);
mapView = new MapView(View.Frame);
mapView.MyLocationEnabled = true;
mapView.BuildingsEnabled = false;
mapView.SetMinMaxZoom(15f, 18f);
View = mapView;
}
private void SetBottomSheet()
{
var bottom = UIScreen.MainScreen.Bounds.Height - UIApplication.SharedApplication.StatusBarFrame.Height;
bottomSheetViewController = new BottomSheetViewController(100, 300, bottom, true, BottomSheetState.Middle);
AddChildViewController(bottomSheetViewController);
View.AddSubview(bottomSheetViewController.View);
bottomSheetViewController.DidMoveToParentViewController(this);
bottomSheetViewController.View.Frame = new CGRect(0, View.Frame.GetMaxY(), View.Frame.Width, View.Frame.Height);
}
How can I wire these two views (mapView and bottomSheetViewController.View) in order to not lose the drag up/down feature from the BottomSheet control?
Even if the question is for Xamarin, an answer from swift or objective-c will do just fine as I will do the 'translation' afterwards.
I had a similar project, my solution at that time was to set the ConsumeGesturesInView property to false.
So your SetMap() method should look like this:
private void SetMap()
{
var frame = new CGRect(0, View.Frame.GetMaxY(), View.Frame.Width, View.Frame.Height);
mapView = new MapView(View.Frame);
mapView.MyLocationEnabled = true;
mapView.Settings.ConsumeGesturesInView = false;
mapView.BuildingsEnabled = false;
mapView.SetMinMaxZoom(15f, 18f);
View = mapView;
}
I have ViewContoller, and it is view hierarchy is the following (Cirrious.FluentLayout Library, but It should be understandable):
_scrollView = new UIScrollView()
{
ShowsVerticalScrollIndicator = false
};
View.Add(_scrollView);
_contentView = new UIView();
_scrollView.Add(_contentView);
View.AddConstraints(
_scrollView.Below(VueNavBar),
_scrollView.AtLeftOf(View),
_scrollView.AtRightOf(View),
_scrollView.AtBottomOf(View)
);
_scrollView.AddConstraints(_contentView.SameFrameAs(_scrollView));
Then I add UISwitch in the following way:
var switch = new UISwitch();
_contentView.Add(switch);
After setting up constraints (I have tried many sets of constraints, many of them are definitely not ambiguous) iOS renders me the following:
It is really weird, but after toggling it changes to:
Maybe someone have any ideas why it happens?
P.S.: I have managed to broke switches on other pages by adding scroll view in the same way, however they have been broken in a differently (Other type of glitch).
I tried the code below and the switch displayed normally.
And there is no need for you to define the width and height of a UISwitch.
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Perform any additional setup after loading the view, typically from a nib.
_scrollView = new UIScrollView()
{
ShowsVerticalScrollIndicator = false,
BackgroundColor = UIColor.Blue
};
View.Add(_scrollView);
this.View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
_scrollView.AtTopOf(View,20),
_scrollView.AtLeftOf(View,20),
_scrollView.AtRightOf(View, 20),
_scrollView.AtBottomOf(View, 20)
);
_contentView = new UIView();
_contentView.BackgroundColor = UIColor.Orange;
_scrollView.Add(_contentView);
_scrollView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
_scrollView.AddConstraints(
_contentView.WithSameTop(_scrollView),
_contentView.WithSameLeft(_scrollView),
_contentView.WithSameWidth(_scrollView),
_contentView.WithSameHeight(_scrollView)
);
var switch1 = new UISwitch();
_contentView.Add(switch1);
_contentView.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
_contentView.AddConstraints(
switch1.AtTopOf(_contentView, 80),
switch1.AtLeftOf(_contentView, 20)
);
}
So I am trying to create a feature for a mobile app.
It needs to be able to display a pdf file in a view and allow a user to place a sizeable picture of his signature on desirable location.
I am working with xamarin.forms and to display a pdf file using this:
https://github.com/xamarin/recipes/tree/master/Recipes/xamarin-forms/Controls/display-pdf
Now I need to know what is the best approach for the second part.
A user places an image and all I need is to get coordinates of the location and its width.
So far I see two possible ways:
Create two views on top of each other, the first for pdf and second for the signature. Allow manipulation of the image in the second and get data from there. Not sure how to do it or if it is a good idea.
Make IOS use pdfjs in the same way as Android (having troubles with that) and on pdfjs side implement fabric.js and then get data from there.
Any suggestions or ideas for a better way to do it?
Thanks
You can add image and signature into webView.ScrollView , and make some adjustments on its ContentInset.
Change webView.ScrollView.ContentInset first.
Add additional view .
Make the webView scroll to the correct location(original anchor).
Complete code :
class MyDelegate: UIWebViewDelegate
{
public override void LoadingFinished(UIWebView webView)
{
webView.ScrollView.ContentInset = new UIEdgeInsets(200, 0, 0, 0);
UIView view = new UIView(frame: new CoreGraphics.CGRect(0, -200, webView.Frame.Width, 200));
UIImageView image = new UIImageView(frame: new CoreGraphics.CGRect(0, 0, webView.Frame.Width, 100));
UILabel label = new UILabel(frame: new CoreGraphics.CGRect(0, 100, webView.Frame.Width, 100));
view.Add(image);
view.Add(label);
webView.ScrollView.AddSubview(view);
webView.ScrollView.ContentOffset = new CoreGraphics.CGPoint(0, -200);
}
}
public class CustomWebViewRenderer : ViewRenderer<CustomWebView, UIWebView>
{
protected override void OnElementChanged (ElementChangedEventArgs<CustomWebView> e)
{
base.OnElementChanged (e);
if (Control == null) {
UIWebView web = new UIWebView();
web.Delegate = new MyDelegate();
SetNativeControl(web);
}
}
//xxxxx
}
How to have a tag bubbles like in the attached image.I have done this for android using TagView component but not sure how to do it for Xamarin iOS?Any component that I can refer?
You will have to write this custom component yourself .
I would recommend having this designed in XIB/Storyboard and place em at runtime .
very rough idea to create one such subview programmitically could be something like
var myView = new UIView(frame: new CoreGraphics.CGRect(10, 10, 120, 40));
myView.BackgroundColor = UIColor.Blue;
myView.Layer.CornerRadius = 20;
var mylabel = new UILabel(frame: new CoreGraphics.CGRect(10, 10, 80, 40));
mylabel.Text = "MUMBAI";
myView.Add(mylabel);
UIButton button = new UIButton();
button.Frame = new CoreGraphics.CGRect(mylabel.Frame.X + mylabel.Frame.Width, 10f, 40, 25);
button.SetTitle("Title", UIControlState.Normal);
button.SetBackgroundImage(UIImage.FromBundle("MyImage"),UIControlState.Normal);
myView.Add(button);
View.Add(myView);
Here frame calculation you need to do ,above are just some sample frame I put .
so ultimately you gonna make such views stack em horizontally ,and when user clicks "x" button , you change the frame with animation .
Try this
https://github.com/nmilcoff/TagsView
It's super simple to get started:
public class ViewController : UIViewController
{
private TagListView tagsView;
public override void ViewDidLoad()
{
// code
this.tagsView = new TagListView()
{
// you can customize properties here!
};
this.View.AddSubview(this.tagsView);
this.View.AddConstraints(
// Add your constraints!
);
// you can attach a source object to each tag
var myObject = new MyModel { Title = "I'm a MyModel!" };
this.tagsView.AddTag(myObject.Title, myObject);
// but, if none is provided, it will be the text string
this.tagsView.AddTag("I'm a simple tag!");
}
}
I'm having an issue asynchronously loading several UIWebViews into one Section. I'm using MonoTouch.Dialog to generate the UI. I am loading data from a blog and showing 10 items which consist of an image plus some HTML text. What's happening is that the posts are not all showing up and the ones that are showing up are out of order. Here's what I'm doing:
public partial class BlogViewController : DialogViewController
{
private Section mainSection;
public BlogViewController () : base (UITableViewStyle.Grouped, null)
{
Root = new RootElement ("");
mainSection = new Section ("");
mainSection.Add(new ActivityElement ());
Root.Add (mainSection);
}
public override void ViewDidLoad()
{
base.ViewDidLoad ();
new Thread (new ThreadStart(PopulateBlog)).Start ();
}
private void PopulateBlog ()
{
var posts = service.GetPosts (currentOffset, 10);
InvokeOnMainThread (delegate {
foreach (var post in posts) {
//grab an appropriate image size
var altSize = post.photos [0].alt_sizes.Where (x => x.width < 401).OrderByDescending(x => x.width).FirstOrDefault ();
if (altSize != null) {
var img = LoadImageFromUri(altSize.url);
//scale the image, not really important
var imageView = new UIImageView (new RectangleF (0, 0, screenWidth, height));
imageView.Image = img;
var content = new UIWebView ();
//When the HTML finishes rendering figure out the size and add it to the section. Apparently can't figure the size ahead of time?
content.LoadFinished += (sender, e) =>
{
var contentHeight = Int32.Parse (content.EvaluateJavascript ("document.getElementById('content').offsetHeight;"));
content.Frame = new RectangleF (0, height + 10, screenWidth, contentHeight + 10);
//dynamically size this view to fit the content
var view = new UIView
(new RectangleF (0, 0,
screenWidth,
height + contentHeight));
view.AddSubview (content);
view.AddSubview (imageView);
//add the view to the Section which is later added to the Root
mainSection.Add(view);
};
var htmlString = #"some HTML here";
content.LoadHtmlString(someHtml);
content.ScrollView.ScrollEnabled = false;
content.ScrollView.Bounces = false;
}
}
});
Root.Reload(mainSection, UITableViewRowAnimation.None);
}
}
I'm guessing that A) the LoadFinished events are not happening in the same order that they are queued up, and that B) The Root.Reload gets called before they all fire. I tried spinning with a Thread.Sleep prior to the Root.Reload but then the LoadFinished events never even get fired.
I also tried putting all of the UIView elements in a Dictionary to be added after they are all populated but it seems like as soon as InvokeOnMainThread ends the LoadFinished event handler never gets called again.
Do you have to use MT.Dialog? I would personal try to use UITableView instead. Load the web view content, determine its size (maybe use sizeThatFits?) and push it to the data source at correct location. Then return the size on the UITableViewDelegate's heightForRowAtIndexPath call. UITableView should take care of the rest.