Reposition legal label ( MKAttributionLabel )
Asked Answered
F

7

16

I'd want to move the Legal label to the right side. On iOS 6 and 7 the below solution was working fine, however on iOS 8.3 it seems to not work.

I get the label, then with a timer (0.1 sec) in viewDidLayoutSubviews I call this method :

-(void)moveLegalLabel
{
    UIView * legalLink = [self attributionView];
    legalLink.frame = CGRectMake(self.mapView.frame.size.width - legalLink.frame.size.width - 10, self.mapView.frame.size.height - legalLink.frame.size.height - 10 , legalLink.frame.size.width, legalLink.frame.size.height);
    legalLink.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
}

which works nicely for rotation, etc. But as soon as I scroll the map, the label jumps back to the left. Tried to call this method in the regionDidChangeAnimated but the label jumps back first to the left then to right, it's really annoying...

How could I force that stupid label to stay on the right side ?

Solution as suggested by Christian :

  1. Subclass the MKMapView
  2. Move the moveLegalLabel code there
  3. Call it in layoutSubviews

-(void)layoutSubviews { [super layoutSubviews]; [self moveLegalLabel]; }

Freshwater answered 9/6, 2015 at 14:59 Comment(8)
Why on earth would you do that with a 0.1 delay?Doubles
@ChristianSchnorr Because I need to preserve the label on the right even after rotation. The main problem is the map repositions that label after each region change...Freshwater
Then how about you hook into after the rotation (but without a delay!) and undo whatever the map did?Doubles
@ChristianSchnorr That's what I am doing, but as I said, that is working fine, with or without a delay. The problem is the map repositions that stupid label when I change the map's region ( scroll/zoom the map ). And the moveLegalLabel inregionDidChangeAnimated works randomly. Sometimes it keeps the label on right, sometimes not ...Freshwater
That's because the hook you use to position it is wrong. Try subclassing the map and overriding -layoutSubviews.Doubles
@ChristianSchnorr You are absolutley right. It indeed works this way. I thought I could avoid subclassing because calling moveLegalLabel in viewDidLayoutSubviews should be called after each view's own layoutSubviews... Thank you really much.Freshwater
Should I put this into an answer so you can accept it or will you accept one of the other answers?Doubles
@ChristianSchnorr Feel free to do so. I'd be happy to accept it :)Freshwater
D
3

Hooks like -viewDidAppear:, -mapView:regionWillChangeAnimated: or -mapView:regionDidChangeAnimated:, like others suggested, are not suited for this purpose.

You best bet would be to subclass MKMapView and layout your label in -layoutSubviews after calling super.

Doubles answered 25/6, 2015 at 15:46 Comment(0)
D
8

You need it to be in viewDidAppear and both of the MKMapViewDelegate methods. If you don't put it in both delegate methods you will get the jumping that you saw. That's all!

-(void)viewDidAppear:(BOOL)animated
{
    [self moveLegalLabel];
}

- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    [self moveLegalLabel];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    [self moveLegalLabel];
}

-(void)moveLegalLabel
{
    UIView * legalLink = [self.map.subviews objectAtIndex:1];
    legalLink.frame = CGRectMake(self.map.frame.size.width - legalLink.frame.size.width - 10, self.map.frame.size.height - legalLink.frame.size.height - 10 , legalLink.frame.size.width, legalLink.frame.size.height);
    legalLink.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
}
Dasya answered 17/6, 2015 at 20:24 Comment(4)
It's somewhat better, but it still jumps randomly... With regionWillChangeAnimated implemented, indeed, the label stays on the right side while I move the map, which is nice. But after that in regionDidChangeAnimated soemtimes works, sometimes randomly jumps back...Freshwater
Hmmm im testing on iOS 8 on simulator and it's working fine. Are you repositioning the label anywhere else?Dasya
No ... I commented it even in viewDidLoad . What simulator do you have ? 8.3 ?Freshwater
I tested on all simulators and a 8.3 device and the problem still exists. It works for like 30% of the cases.Freshwater
J
5

A Swift 4 example:

  • Working on iOS 11

  • No need for sub-classes

(based off of Erik's answer)

func viewDidAppear(_ animated: Bool) {
   moveLegalLabel()
}

func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
   moveLegalLabel()
}

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
   moveLegalLabel()
}

func moveLegalLabel() {
   let legalLabel: UIView = mapView.subviews[1]
   legalLabel.frame=CGRect(x: mapView.frame.size.width - (legalLabel.frame.size.width ?? 0.0) - 10, y: mapView.frame.size.height - (legalLabel.frame.size.height ?? 0.0) - 10, width: legalLabel.frame.size.width ?? 0.0, height: legalLabel.frame.size.height ?? 0.0)
}
Japhetic answered 26/7, 2018 at 8:51 Comment(1)
Works with iOS 13.6Kaiserism
D
3

Hooks like -viewDidAppear:, -mapView:regionWillChangeAnimated: or -mapView:regionDidChangeAnimated:, like others suggested, are not suited for this purpose.

You best bet would be to subclass MKMapView and layout your label in -layoutSubviews after calling super.

Doubles answered 25/6, 2015 at 15:46 Comment(0)
H
1

Try to use transform this way:

- (void)moveLegalLabel
{
    UIView *legalLink = [self attributionView];
    legalLink.transform = CGTransformMakeTranslation(self.mapView.frame.size.width - CGRectGetMaxX(legalLink.frame) - CGRectGetMinX(legalLink.frame), self.mapView.frame.size.height - CGRectGetMaxY(legalLink.frame) - CGRectGetMinY(legalLink.frame));
}

If not works try to use layer.transform:

- (void)moveLegalLabel
{
    UIView *legalLink = [self attributionView];
    legalLink.layer.transform = CATransform3DMakeTranslation(self.mapView.frame.size.width - CGRectGetMaxX(legalLink.frame) - CGRectGetMinX(legalLink.frame), self.mapView.frame.size.height - CGRectGetMaxY(legalLink.frame) - CGRectGetMinY(legalLink.frame));
}
Hyphen answered 20/6, 2015 at 20:46 Comment(0)
F
0

You must load your code in viewDidAppear, before it your code may not take place. Apparently your code was being compiled before the views were ready.

-(void)moveLegalLabel
{
    UIView * legalLink = _mapView.subviews[1];
    legalLink.frame = CGRectMake(self.mapView.frame.size.width - legalLink.frame.size.width - 10, self.mapView.frame.size.height - legalLink.frame.size.height - 10 , legalLink.frame.size.width, legalLink.frame.size.height);
    legalLink.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
}


-(void)viewDidAppear:(BOOL)animated {
    [self moveLegalLabel];
}

If you create a button and put your code in its action, when you click you can see the label moving.

Foliolate answered 17/6, 2015 at 21:27 Comment(0)
M
0

Here I moved it from the bottom to the top:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

    // Move legal notice since covered in design
    mapView.subviews
        .first { "\(type(of: $0))" == "MKAttributionLabel" }?
        .frame.origin.y = mapView.frame.minY + 10
}
Maplemaples answered 15/2, 2018 at 15:44 Comment(0)
C
-1

For solution this problem you can:

1.Create Subclass (MKMapView)

class CustomMapView: MKMapView {

}

2.Override layouSubviews like this:

override func layoutSubviews() {
        super.layoutSubviews()
        let legalLabel: UIView = self.subviews[1]
        let frame = .....
    }

This way works for me

Canicula answered 25/4, 2018 at 13:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.