nativescript marshalling error - ios

I seem to be getting a strange problem when marshaling the following native iOS code to nativescript:
CGRect keyboardRect = CGRectMake(0, 0, self.view.frame.size.width, 216);
AGEmojiKeyboardView *emojiKeyboardView = [[AGEmojiKeyboardView alloc] initWithFrame:keyboardRect
dataSource:self];
emojiKeyboardView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
emojiKeyboardView.delegate = self;
self.textView.inputView = emojiKeyboardView;
The equivalent I came up with is the following:
var keyboardRect = CGRectMake(0, 0, platform.screen.mainScreen.widthPixels, 216);
var emojiKeyboardView = new AGEmojiKeyboardView();
emojiKeyboardView.frame = keyboardRect;
emojiKeyboardView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
emojiKeyboardView.delegate = this;
views.textInput.ios.inputView = emojiKeyboardView;
where platform is just require("platform"); and views.textInput is a view to which I need to set the inputView to AGEmojiKeyboardView.
I really don't understand where I went wrong. All that appears is a grey keyboard with no content.
EDIT:
I changed the js code to the following:
var keyboardRect = CGRectMake(0, 0, uiView.view.frame.size.width, 216);
var emojiKeyboardView = new AGEmojiKeyboardView(keyboardRect, uiView);
emojiKeyboardView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
emojiKeyboardView.delegate = uiView;
views.textInput.ios.inputView = emojiKeyboardView;
where uiView is just page.ios and something seems to happen now, but still not the intended result. An exception is thrown, namely the following: -[UIViewControllerImpl emojiKeyboardView:imageForSelectedCategory:]: unrecognized selector sent to instance 0x7e6bff60

As NativeScript has TypeScript as first-class member somethings are really easier to do with TS. For example you can also use the META-Generator
Simply run this two lines to generate metadata & typings for your CocoaPod (and all other Objective-C files) and you won't have to worry about the right syntax.(still you will need to know the basic rules)
TNS_DEBUG_METADATA_PATH="$(pwd)/metadata" tns build ios [--for-device] [--release]
TNS_TYPESCRIPT_DECLARATIONS_PATH="$(pwd)/typings" tns build ios [--for-device] [--release]
Also if you want to createa a custom view the best variant is using NativeScript placeholder with creatingView
As for the syntax it shouldb look similar to this but still you will have to create your own ViewController and as the author says - conform to AGEmojiKeyboardViewDataSource and AGEmojiKeyboardViewDelegate protocol.
var frame = require('ui/frame');
var page;
function onLoaded(args) {
page = args.object;
}
exports.onLoaded = onLoaded;
function onCreatingView(args) {
setTimeout(function() {
var uiView = page.ios.view; // replace with own UIView and conform to AGEmojiKeyboardViewDataSource and AGEmojiKeyboardViewDelegate protocol.
var frame = {origin: {x:0, y:0}, size: {width: uiView.frame.size.width, height:600}};
var emojiView = AGEmojiKeyboardView.alloc().initWithFrameDataSource(frame, uiView);
emojiView.autoresizingMask = UIView.UIViewAutoresizing.UIViewAutoresizingFlexibleHeight;
emojiView.delegate = uiView;
var textContainer = NSTextContainer.alloc().initWithSize({width: 80, height: 180});
var frame = {origin: {x:0, y:0}, size: {width: 100, height:220}};
var textView = UITextView.alloc().initWithFrameTextContainer(frame, textContainer);
textView.inputView = emojiView;
args.view = textView;
}, 500);
}
exports.onCreatingView = onCreatingView;
page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded">
<StackLayout>
<Placeholder creatingView="onCreatingView" id="placeholder-view"/>
</StackLayout>
</Page>

I could be mistaken, but I don't think you are using marshalling properly.
The documentation states:
AGEmojiKeyboardView *emojiKeyboardView = [[AGEmojiKeyboardView alloc] initWithFrame:keyboardRect dataSource:self];
So your {N} version should be something like this:
var emojiKeyboardView = AGEmojiKeyboardView.alloc().initWithFrameDataSource(keyboardRect, uiView);
This is a great blog-post on how to create plugins based on 3rd party libraries for nativescript. It also explains step-by-step how this type of marshalling is done.
http://fluentreports.com/blog/?p=167

Related

UILabel with Image and text in iOS(Xamarin)

I am making UILabel with Image and text inside that.I try many thing like below.
Try 1 :
Using this code
var textAttchment = new NSTextAttachment();
textAttchment.Image = UIImage.FromBundle("location_grey_icon");
var attachmentString = NSAttributedString.FromAttachment(textAttchment);
var attributedString = new NSMutableAttributedString(lbl_inr.Text.ToString());
this.lbl_inr.AttributedText = attributedString;
But it only display the Text not the image.
Try 2:
using this code
var attchment = new NSTextAttachment();
attchment.Image = UIImage.FromBundle("location_grey_icon");
attchment.Bounds = new CGRect(0, -1, 13, 13);
var intiliazeText = this.text_inr.AttributedText;
var newText = new NSMutableAttributedString(intiliazeText);
newText.Append(NSAttributedString.CreateFrom(attchment));
this.text_inr.AttributedText = newText;
it is display the Image and Text both.
Output :
What I want :
but my requirement is to I want to set image before the Text so first Image and then Text.
Any help be Appreciated.
Your requirement is very specific, the best way to do this would be with a custom control.
UIView + Label + UIImageView
and there you could set your bounds to your needs. With the designer this is a simple task.
Or you could try with a UITextField, removing the borders and disabling it. Then adding a UIImageView as the RightView (or LeftView as you wish).
var textEdit = new UITextField (new CGRect (15, 100, 200, 30));
textEdit.Enabled = false;
textEdit.Text = "Hello from Xamarin";
var xamImageView = new UIImageView (new CGRect (0,0, 25, 25));
xamImageView.Image = UIImage.FromBundle ("xamagon");
textEdit.RightView = xamImageView;
textEdit.TextAlignment = UITextAlignment.Right;
textEdit.RightViewMode = UITextFieldViewMode.Always;
textEdit.BorderStyle = UITextBorderStyle.None;
Result:
Hope this helps!
Using below code I manage
var attchment = new NSTextAttachment();
attchment.Image = UIImage.FromBundle("location_grey_icon");
attchment.Bounds = new CGRect(0, -2, 14, 14);
var newText = new NSMutableAttributedString();
newText.Append(NSAttributedString.CreateFrom(attchment));
NSAttributedString s = new NSAttributedString(item.Total.ToString());
newText.Append(s);
this.lbl_inr.AttributedText = newText;
Output :

How to create UIStackView from code correctly

I can't understand why this layout won't render the way i need it. Completing the requirement on android with linearlayouts should be equivalent to this?
What i get:
What i need:
My code:
// my stackview only renders at all if i pass any height > 0 && width > 0,
// but i would love this to be as small as possible, given that all children
// are rendered.
var stackView = new UIStackView(View.Frame);
stackView.Axis = UILayoutConstraintAxis.Vertical;
stackView.Distribution = UIStackViewDistribution.Fill;
foreach (var deviceVm in devices)
{
// i would prefer this not to have a rect parameter and scale as needed.
var descriptionLabel = new UILabel(new CGRect(0, 0, View.Bounds.Width, 20));
descriptionLabel.Text = deviceVm.Description;
descriptionLabel.TextColor = UIColor.Blue;
descriptionLabel.ContentMode = UIViewContentMode.ScaleToFill;
stackView.AddArrangedSubview(descriptionLabel);
}
// i assume this should make it as small as possible, as big as necessary?
stackView.SizeToFit();
var scrollView = new UIScrollView(View.Frame);
scrollView.BackgroundColor = UIColor.Yellow;
scrollView.AddSubview(stackView);
View.AddSubview(scrollView);
Can someone spot a mistake i am doing here? Am i configuring the StackView incorrectly or is this control not the equivalent of LinearLayout(android) / StackPanel(wpf) ?
PS: Sorry for eye cancer paint pictures.

Using variables in CGRectMake, Swift, UIkit

For an App I'm making i need to use variables to change the size and position of objects (Labels). I've tried var example = CGRectMake(0, 0, 0, 100), hoping it would ignore the zeros (Not really thinking it would though). I then tried:
var example = 100
Label1.frame = CGRectMake(20, 20, 50, example)
I changed the syntax a bit, adding "" and replacing the CGRectMake with CGRect etc, but nothing worked... I don't get what I'm doing wrong here... Help!
Below is the new syntax used since Swift 3.
CGRect(x: 0, y: 0, width: 100, height: 100)
CGRectMake takes CGFloats for all of its arguments. Your sample code should work fine if you specify that example is supposed to be a CGFloat, using a type identifier:
// v~~~~ add this...
var example: CGFloat = 100
Label1.frame = CGRectMake(20, 20, 50, example)
Otherwise, swift infers the type of example to be Int, and the call to CGRectMake fails, cuz it can't take an Int as a parameter...
So, there is many ways to skin the cat. It all depends what your needs and requirements are (maybe you could elaborate a bit on what you are trying to achieve?). But one way to do it could be to set a variable when something happens, and then update the frame of the label. If you added a tap gesture recognizer to your view, and updated your label like so:
let myLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
let tapGestRecog = UITapGestureRecognizer(target: self, action: "handleTap:")
self.view.addGestureRecognizer(tapGestRecog)
}
func handleTap(sender:UIGestureRecognizer) {
let newXposition = sender.locationInView(self.view).x
let newYposition = sender.locationInView(self.view).y
myLabel.frame = CGRectMake(newXposition, newYposition, 200, 200)
}
This is just an example, and a very crude way of doing it. There are many other ways of doing it, but it hopefully gives you an idea of how to achieve it.
Swift allows syntax that Objective-C does not:
var example = 100
label.frame.size.height = example
In objective-C you would have to do it differently:
CGRect frame = label.frame; //Create a temporary rect to hold the frame value
frame.size.height = example;
label.frame = frame;

How to create a variable number of UIImageViews in swift

My problem is that based on the number of groups a person has I want to dynamically create that many UIImageView and assign them to the view. I know how to create a single UIImageView and put it onto the view but how can I create a variable number of them since creating another with the same name seems to just overwrite the original? I tried sending the UIImageView into an Array but got an optional error.
circleView = UIImageView(frame:CGRectMake(125, y, 75, 75))
y+=150
circleView.image = UIImage(named:"circle.png")
circleView.tag = i
self.view.addSubview(circleView)
circleArray[i] = circleView
The problem is that you keep reusing the same circleView instance. When you add it to the array, you are just adding a reference to it. You then reinitialize it, which wipes it out. I also don't see where you are incrementing i. Try something like this:
var circleArray = Array<UIImageView>()
var y : CGFloat = 0.0
var i = 0
circleArray.append(UIImageView(frame:CGRectMake(125, y, 75, 75)))
var circleView = circleArray[i]
circleView.image = UIImage(named:"circle.png")
circleView.tag = i
self.view.addSubview(circleView)
y+=150
i += 1
You need to use circleArray.append(circleView)

AS2 textField hyperlink

I have to add something to an existing as2 project. I know as3 pretty well, but as2 doesn't make sense to me at all. Basically what I have to do is add a link to the bottom of every "page". The link changes depending on what "page" you are on. I have variables passing, so all I need to do is create the link.
//Url gets passed here
var urlString;
createTextField("urls", 1, 300, 499, 150, 30);
urls.setNewTextFormat(my_fmt);
urls.text = urlString;
Now I have to turn "urls" into a link. What would be the best way to do this?
This would be one possible solution: Create a movieclip to hold the textfield and then use it as a button...
//Url gets passed here
var urlString = "the URL";
this.createEmptyMovieClip("urlHolder", 1);
urlHolder._x = 300;
urlHolder._y = 499;
urlHolder.createTextField("urls", 1, 0, 0, 150, 30);
//urlHolder.urls.setNewTextFormat(my_fmt);
urlHolder.urls.text = urlString;
urlHolder.onRelease = function(){
getURL("www.google.com");
}

Resources