I 've been trying to add a half circle to a map view using a custom MKOverlayPathView subclass and a custom class which confirms to but I cannot get anything to show up on the map view. I use a UIBezierPath to create the path for the circle, but no matter what I try, I cannot see my path...
Does anyone have an example program in which a UIBezierPath is being used as overlay?
Thank you!
Tim
Edit: Answer to Anna's question:
I can draw MKCircleViews without any problem, but I seem to struggle with custom subclasses for MKOVerlay(Path)View. The delegate is set, and an NSLog confirms that my overlay is actually added, only the View part is missing ...
Below the header file for my overlay class. Comments and variables are in Dutch, if anyone wants a translation I can provide it but I think everything should be clear. I create a overlay with centre coordinate and radius.
The boundingMapRect is calculated from the centre coordinate. Origin is centre minus the radius for both x and y, and the width + height are twice the radius.
#interface PZRMijnOverlay : NSObject <MKOverlay>
{
}
//een property die een bezierpath beschrijft, naar de 2 standaard overlay properties
#property (nonatomic, strong) UIBezierPath *bezierPath;
#property (nonatomic) CLLocationDistance straal;
//class method
+(PZRMijnOverlay *)bezierCirkelMetCenterCoordinate: (CLLocationCoordinate2D)coordinaat enStraal: (CLLocationDistance)eenStraal;
//een eigen designated init
-(id)initWithCenterCoordinate: (CLLocationCoordinate2D)coordinaat enStraal: (CLLocationDistance)eenStraal;
#end
This is de viewForOverlay method implementation:
PZROverlayView *overlayView = [[PZROverlayView alloc] initWithOverlay:(PZRMijnOverlay *)overlay];
overlayView.strokeColor = [UIColor redColor];
overlayView.lineWidth = 10;
//overlayView.strokeColor = [UIColor blackColor];
return overlayView;
Now I guess I should overwrite the createPath method in my PZROverlayView class, but I cannot figure out what code needs to go there. What I tried was to create a UIBezierPath, convert it to CGPath and assign it to the path property of the MKOverlayPathView super class.
Alright, I finally found what I was doing wrong! It is actually way easier than I thought!
Solution:
Add MKCircle overlay
In viewForOverlay: create a bezierPath (CG or UI) and add it to the path property of a standard MKOverlayPathView instance
I was making it myself way too difficult by using custom classes...
Related
Anyone knowns how to set round corner to the video frame using AVPlayer?
I'm trying doing this:
- (void)loadVideoWithPlayer:(AVPlayer*)playerVideo
{
dispatch_async(dispatch_get_main_queue(), ^{
AVPlayerLayer *avLayer = [AVPlayerLayer playerLayerWithPlayer: playerVideo];
[avLayer setCornerRadius:20];
[avLayer setMasksToBounds:YES];
[self.playerViewController setPlayer:playerVideo];
[self insertSubview:self.playerViewController.view belowSubview:self.interactView];
[self.playerViewController.player play];
});
}
but it's not working. I can't set round corners to the AVPlayer.playerViewController.view because the video frame could be different.
I was just able to do this. The change could even be animatable, from no rounder corners to rounded corners.
I didn't do anything much different from you. Using iOS 10 at the moment. (Confirmed working on iOS 9.3.5 device also.)
self.viewVideo?.layer.masksToBounds = SHOW ? true : false
self.viewVideo?.layer.cornerRadius = SHOW ? 10 : 0
I should perhaps note that the viewVideo is a subclass of UIView. The only real change there is the layerClass being returned as AVPlayerLayer.self
override static var layerClass: AnyClass {
return AVPlayerLayer.self
}
So btw I do not use AVPlayerViewController etc. I just add my subclass of UIView to my usual UIViewController's view.
I am new to this. And there comes my first problem.
I build an object loader with SceneKit. I got the path, the Object is available, but I have no clue how I can color the shown object.
ScnScene *testScene = [SCNScene sceneWithURL:url options:nil error:NULL];
testScene.background.contents = [UIImage imageWithName:#"color.png"];
[self.mainView.scene.rootnode addChildNode:testScene.rootNode];
This didn't work. I also tried with:
SCNMaterialProperty *testColor = [SCNMaterialProperty materialPropertyWithContents [UIImage imageNamed:#"color.png"]];
testScene.rootnode.geometry.materials = testcolor;
Or:
SCNMaterial *testColor = [SCNMaterial material];
testColor.diffuse.contesnts = [UIColor redColor];
testScene.rootnode.geometry.firstMaterial = testColor;
Nothing works. When I start the app, every object is displayed. So far the OBJ-Loader works out very well. But everything is still gray. I totally have no clue how to color the displayed objects. Has anyone a hint/idea/solution for me?
Btw. I want to avoid that I have to build a geometry out of the OBJ-Informations manually. So I try to solve this by the SCNScene.
The major problem was that the import by a SCNScenedoes not work that way. So the right solution is to import the obj.file into a SCNNode, add a SCNMaterial with the chosen color (or an image) to the SCNNode and give the SCNNodeto the SCNScene. To load the obj.file, you need to import that by Model IO Framework.
I will give some code how I made it colorful.
#import <SceneKit/SceneKit.h>
#import <ModelIO/ModelIO.h>
#import <SceneKit/ModelIO.h>
...
#property (nonatomic) SCNView* mainView;
....
MDLAsset *asset = [[MDLAsset alloc] initWithURL:url];
SCNScene *scene = [SCNScene scene];
SCNNode *node = [SCNNode nodeWithMDLObject:[asset objectAtIndex:0]];
SCNMaterial *material = [SCNMaterial material];
material.diffuse.contents = [UIColor colorWithHue:0 saturation:0.1 brightness:0.5 alpha:1];
node.geometry.firstMaterial = material;
[scene.rootNode addChildNode:node];
[self.mainView.scene.rootNode addChildNode:scene.rootNode];
Alternately you can add a color by this:
material.diffuse.contents = [UIImage imageNamed:#"farbe.png"];
Now you can import any obj.file externally (from any chosen folder you like) and color it.
Thanks to SGlindemann, cashmash and Hal Mueller, who helped out to find that solution.
UPDATE (29.1.2017)
Somehow the way above does not work anymore. I did not figure out yet what changed. But I made another code that makes loading for 3D files possible (from mainBundle, not externally). Here I start from a SCNNode class which is called by the ViewController.m. The SCNScene is setup in the ViewController. Following there is the code which I wrote for the SCNNode class.
Before you start, put the .obj and .mtl file (both with same name) into your Xcode project. You don't need to convert it to a scene.
#import <ModelIO/ModelIO.h>
#import <SceneKit/ModelIO.h>
...
#property (nonatomic) SCNNode *objectNode;
...
NSString* path = [[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat:#"name of the obj.file"]
ofType:#"obj"];
NSURL *url = [NSURL fileURLWithPath:path];
MDLAsset *asset = [[MDLAsset alloc]initWithURL:url];
// Create the Block
self.objectNode = [SCNNode nodeWithMDLObject:[asset objectAtIndex:0]];
[self addChildNode: self.objectNode];
return self;
This returned self has to be added into your view.
[self.view.scene.rootNode addChildNode:returnedObj];
The MDLAssetloads the .obj-file with the corresponding .mtl-file and png-File. I used this code to load objects from MagicaVoxel (this exports obj+mtl+png at once). I did not get deep into it yet.
I did NOT try this code with external loadings or typing in colors manually via SCNMaterial. So there is no statement whether this works or not. I did not try.
Your first example will set the background of the scene but do nothing with your object.
Your second example should be giving you some compiler warnings. You're assigning a single SCNMaterialProperty to testScene.rootnode.geometry.materials, which expects an array of SCNMaterial (not SCNMaterialProperty). Is that your real code?
The final example shouldn't compile at all: you've misspelled contents as contesnts. Other than that, it ought to work.
Note that MDLAsset can import an OBJ file and return an SCNNode. See How do you convert Wavefront OBJ file to an SCNNode with Model I/O. If the object is an asset you'll be shipping with your project, save it as an SCNScene (which is compact and optimized), and ship that, not the original OBJ.
Well, Ive searched in several places and although some people allegedly have found fixes it doesn't seem to apply to my case.
I'm trying to procedurally set the line height of a few UItextviews like this :
UITextView *lab = [LocalTexts objectAtIndex:j];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineHeightMultiple = 50.0f;
paragraphStyle.maximumLineHeight = 50.0f;
paragraphStyle.minimumLineHeight = 50.0f;
NSString *string = lab.text;
NSDictionary *ats = #{
NSFontAttributeName : [UIFont fontWithName:#"DIN Medium" size:16.0f],
NSParagraphStyleAttributeName : paragraphStyle,
};
lab.attributedText = [[NSAttributedString alloc] initWithString:string attributes:ats];
Strange thing is that if I disable the NSFontAttributeName assignment, the line height will work, also, if I set the Paragraph style to have a certain paragraph height, that always works too, so the NSParagraphStyleAttribute IS NOT being fully ignored. I dont know if it is a bug or I'm actually doing something wrong.
I tried implementing it as pure CORE TEXT, but it is a bit too complex for the current scope of the project.
Hope someone can point me in the right direction. Thanks.
This is a known bug in NSHTMLWriter which is used by UITextView to convert your attributed string to HTML: http://www.cocoanetics.com/2012/12/radar-uitextview-ignores-minimummaximum-line-height-in-attributed-string/
You can use UITextView replacement we have in DTCoreText to render this text correctly: https://github.com/Cocoanetics/DTCoreText
I am using the following code:
CCMenuItemFont *controllerItem = [CCMenuItemFont itemFromString:#"Analog" target:self selector:#selector(controllerToggle)];
CCMenu *controllerTypeMenu = [CCMenu menuWithItems:controllerItem, nil];
[controllerTypeMenu alignItemsVerticallyWithPadding:30.0f];
controllerTypeMenu.position = CGPointMake(160.0f, 240.0f);
[self addChild:controllerTypeMenu z:0 tag:ControllerMenu];
}
-(void) controllerToggle
{
CCMenuItemFont *controllerItem = [self getChildByTag:888];
NSString * text = [NSString stringWithFormat: #"switching.. %f", CCRANDOM_0_1()];
[controllerItem setString:text];
}
In controllerToggle I would like to access to controllerItem and change the String to another value. Is this possible? I checked and CCMenu adds as child the CCMenuItems based the array order. But that's not an elegant solution. For the same reason I cannot add the CCMenuItem to the Scene as it will give me "child already added error". So I feel I should write my own "switch" button but I wonder if there is already something out there..
Any help?? Thanks!
you can declare needed menu item as class member. In this way you will be able to get access to it whenever you want
There is already CCMenuItemToogle which is used to switching the title or image of any menuitem on click event.Instead of taking CCMenuItem you can use CCMenuItemToggle..
Here is a sample code
CCmenuItemToggle *cam=[CCMenuItemToggle itemWithTarget:self selector:#selector(openCameraController) items:cameraOn,cameraOff, nil];
where cameraOn and cameraOff are two simple CCMenuItemImage which is added in CCMenuItemToggle and further this CCmenuItemToggle is added in a menu.
Now on every click of CCMenuItemToggle there will be a cameraOn and cameraOff state for same menuitem.
Hope this will help...
the problem I am having it that if inside the UIView Draw override, I change the view frame size, drawing a rectangle is not working as expected.
If I change the view frame size outside of the Draw override, it works fine. Is this an expected behavior or is it a problem with monotouch only?
This is the code I am using:
class ChildView : UIView
{
public override void Draw (RectangleF rect)
{
base.Draw (rect);
CGContext g = UIGraphics.GetCurrentContext();
//adding 30 points to view height
RectangleF rec = new RectangleF(this.Frame.Location,this.Frame.Size);
rec.Height+=30;
RectangleF rec_bounds = new RectangleF(0,0,rec.Width,rec.Height);
this.Frame=rec;
this.Bounds=rec_bounds;
//drawing a red rectangle to the first half of view height
UIColor.Red.SetFill();
RectangleF _rect = new RectangleF(this.Bounds.Location,this.Bounds.Size);
_rect.Height=_rect.Height/2;
g.FillRect(_rect);
}
}
However, the output of this code is this: (it should draw only 30 points red, but it draws 60 points)
Here is a link to download the project to reproduce this issue:
www.grbytes.com\downloads\RectangleDrawProblem.rar
Καλημέρα!
This behavior is expected. If you want to change the view's frame inside the Draw override, do it before getting the current context. That is because the graphics context also has a size and that is the size of the view at the time you are retrieving it.
Also, there is no need to set both the Bounds and the Frame of the view. You can just set either of them in this case.
By the way, I don't think you need to call base.Draw(). According to the Apple documentation, "If you subclass UIView directly, your implementation of this method does not need to call super."