web-dev-qa-db-fra.com

Changer la largeur de maître dans UISplitViewController

Le guide de programmation pour iPad indique que le volet gauche du splitView est fixé à 320 points. Mais 320 pixels pour mon contrôleur de vue maître, c'est trop. Je voudrais le réduire et donner plus d'espace au contrôleur de vue de détail. Est-ce possible de toute façon?

Lien vers le document qui parle de largeur fixe.

40
Raj Pawan Gumdal

Si vous sous-classez UISplitViewController, vous pouvez implémenter -viewDidLayoutSubviews et y ajuster la largeur. C'est propre, pas de piratage ou API privée, et fonctionne même avec la rotation.

- (void)viewDidLayoutSubviews
{
    const CGFloat kMasterViewWidth = 240.0;

    UIViewController *masterViewController = [self.viewControllers objectAtIndex:0];
    UIViewController *detailViewController = [self.viewControllers objectAtIndex:1];

    if (detailViewController.view.frame.Origin.x > 0.0) {
        // Adjust the width of the master view
        CGRect masterViewFrame = masterViewController.view.frame;
        CGFloat deltaX = masterViewFrame.size.width - kMasterViewWidth;
        masterViewFrame.size.width -= deltaX;
        masterViewController.view.frame = masterViewFrame;

        // Adjust the width of the detail view
        CGRect detailViewFrame = detailViewController.view.frame;
        detailViewFrame.Origin.x -= deltaX;
        detailViewFrame.size.width += deltaX;
        detailViewController.view.frame = detailViewFrame;

        [masterViewController.view setNeedsLayout];
        [detailViewController.view setNeedsLayout];
    }
}
66
jrc

Dans IOS 8.0, vous pouvez facilement le faire en procédant comme suit:

1. Dans votre MasterSplitViewController.h, ajoutez

@property(nonatomic, assign) CGFloat maximumPrimaryColumnWidth NS_AVAILABLE_IOS(8_0);

2. Dans votre méthode MasterSplitViewController.m viewDidLoad, ajoutez

 self.maximumPrimaryColumnWidth = 100;
 self.splitViewController.maximumPrimaryColumnWidth = self.maximumPrimaryColumnWidth;

C’est une très bonne fonctionnalité simple et facile de IOS 8.

35
SJTriggs

ce code est un travail pour moi

[splitViewController setValue:[NSNumber numberWithFloat:200.0] forKey:@"_masterColumnWidth"];
22
priyanka

Non.


Il y a deux privés propriétés

@property(access,nonatomic) CGFloat masterColumnWidth;
@property(access,nonatomic) CGFloat leftColumnWidth; // both are the same!

mais étant privé, cela signifie qu'ils ne peuvent pas être utilisés pour les applications AppStore.

12
kennytm

iOS 8 a introduit une nouvelle propriété:

// An animatable property that can be used to adjust the maximum absolute width of the primary view controller in the split view controller.
@property(nonatomic, assign) CGFloat maximumPrimaryColumnWidth NS_AVAILABLE_IOS(8_0); // default: UISplitViewControllerAutomaticDimension

Utilisez cette propriété pour ajuster votre contrôleur de vue principal à la largeur souhaitée.

10
Antoine

Voici comment j'ai fait cela dans iOS8 avec Swift.

class MainSplitViewController: UISplitViewController {

    override func viewDidLoad() {

        self.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
        self.maximumPrimaryColumnWidth = 100 // specify your width here
    }
}

Si vous devez modifier la largeur de manière dynamique à partir de votre vue principale/détaillée dans la vue fractionnée, procédez comme suit:

var splitViewController = self.splitViewController as MainSplitViewController
splitViewController.maximumPrimaryColumnWidth = 400
7
romiem

La manière de storyboard serait celle-ci, mentionnée par @Tim:

 enter image description here

De plus, si vous souhaitez que la vue Maître occupe toujours un certain pourcentage de l'écran, vous pouvez utiliser le chemin clé = "preferredPrimaryColumnWidthFraction" et définir la valeur sur 0.2 (pour une taille d'écran de 20%). 

Veuillez noter que "maximumPrimaryColumnWidth" est défini sur 320. Par conséquent, si vous essayez la valeur de pourcentage d'écran de 0,5 (50%), elle ne dépassera pas 320. Vous pouvez ajouter un chemin de clé pour maximumPrimaryColumnWidth si vous devez le remplacer.

5
Travis M.

Aucune des réponses ne fonctionnant pour moi sur iOS7, j'ai donc effectué certaines de mes recherches et créé une solution efficace. Cela impliquera de sous-classer UISplitViewController pour toutes les fonctionnalités.

Je présenterai la réponse comme si nous venions de créer un nouveau projet pour iPad avec toutes les orientations du périphérique et de définir la variable personnalisée UISplitViewController comme contrôleur de la vue principale.

Créez votre UISplitViewController personnalisé. Dans cet exemple, le mien s'appelle MySplitViewController. Tout le code sera basé sur MySplitViewController.m.

Nous allons avoir besoin d'accéder à une méthode à partir de la UISplitViewControllerDelegate donc ajoutez-la et définissez le délégué. Nous allons également configurer un transmetteur délégué si vous devez appeler les méthodes de délégation depuis une autre classe.

@interface MySplitViewController () <UISplitViewControllerDelegate>
@property (nonatomic, weak) id<UISplitViewControllerDelegate> realDelegate;
@end

@implementation MySplitViewController

- (instancetype)init {
    self = [super init];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (void)setDelegate:(id<UISplitViewControllerDelegate>)delegate {
    [super setDelegate:nil];
    self.realDelegate = (delegate != self) ? delegate : nil;
    [super setDelegate:delegate ? self : nil];
}

- (BOOL)respondsToSelector:(SEL)aSelector {
    id delegate = self.realDelegate;
    return [super respondsToSelector:aSelector] || [delegate respondsToSelector:aSelector];
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    id delegate = self.realDelegate;
    return [delegate respondsToSelector:aSelector] ? delegate : [super forwardingTargetForSelector:aSelector];
}

Configurez les contrôleurs de vue principale et de détail.

- (void)viewDidLoad {
    [super viewDidLoad];

    UIViewController* masterViewController = [[UIViewController alloc] init];
    masterViewController.view.backgroundColor = [UIColor yellowColor];

    UIViewController* detailViewController = [[UIViewController alloc] init];
    detailViewController.view.backgroundColor = [UIColor cyanColor];

    self.viewControllers = @[masterViewController, detailViewController];
}

Ajoutons la largeur souhaitée à une méthode pour faciliter la référence.

- (CGFloat)desiredWidth {
    return 200.0f;
}

Nous allons manipuler le contrôleur de vue principal avant de le présenter.

- (void)splitViewController:(UISplitViewController *)svc popoverController:(UIPopoverController *)pc willPresentViewController:(UIViewController *)aViewController {
    id realDelegate = self.realDelegate;

    if ([realDelegate respondsToSelector:@selector(splitViewController:popoverController:willPresentViewController:)]) {
        [realDelegate splitViewController:svc popoverController:pc willPresentViewController:aViewController];
    }

    CGRect rect = aViewController.view.frame;
    rect.size.width = [self desiredWidth];
    aViewController.view.frame = rect;

    aViewController.view.superview.clipsToBounds = NO;
}

Cependant, nous avons maintenant un écran comme celui-ci .enter image description here

Alors allions remplacer une méthode privée. Oui, une méthode privée, il sera toujours acceptable dans l'App Store puisqu'il ne s'agit pas d'une méthode privée de soulignement.

- (CGFloat)leftColumnWidth {
    return [self desiredWidth];
}

Cela concerne le mode portrait. Donc, une chose similaire pour -splitViewController:willShowViewController:invalidatingBarButtonItem: et vous devriez être configuré pour le paysage.

Cependant, rien de tout cela ne sera nécessaire dans iOS8. Vous pourrez simplement appeler une propriété de largeur min et max!

5
cnotethegr8

Étant donné que personne n’a indiqué que cela pouvait être fait à partir d’IB, je voudrais ajouter cette réponse. Apparemment, vous pouvez définir des "attributs d'exécution définis par l'utilisateur" pour UISplitViewContorller avec les détails suivants:

2
Tim

utilisez le code suivant avant d’attribuer à rootviewcontroller. Cela fonctionne pour moi avec iOS 7

[self.splitViewController setValue:[NSNumber numberWithFloat:256.0] forKey:@"_masterColumnWidth"]; self.window.rootViewController = self.splitViewController;

2
xevser

Swift 3.0 vous utilisez comme

let widthfraction = 2.0 //Your desired value for me 2.0    
splitViewController?.preferredPrimaryColumnWidthFraction = 0.40
let minimumWidth = min((splitViewController?.view.bounds.size.width)!,(splitViewController?.view.bounds.height)!)
splitViewController?.minimumPrimaryColumnWidth = minimumWidth / widthFraction
splitViewController?.maximumPrimaryColumnWidth = minimumWidth / widthFraction
let leftNavController = splitViewController?.viewControllers.first as! UINavigationController
leftNavController.view.frame = CGRect(x: leftNavController.view.frame.Origin.x, y: leftNavController.view.frame.Origin.y, width: (minimumWidth / widthFraction), height: leftNavController.view.frame.height)
0
Madasamy

Vous pouvez utiliser GSSplitViewController . Celui-ci fonctionnera sur iOS 7 et 8

splitView = [[GSSplitViewController alloc] init];
splitView.masterPaneWidth = 180;

Vous pouvez également l'inclure en ajoutant pod 'GSSplitViewController' à votre Podfile.

0
o.akrout

Dans mon cas, je devais définir le maximum et le minimum pour que cela fonctionne

mySplitViewController.preferredDisplayMode = .allVisible;
mySplitViewController.maximumPrimaryColumnWidth = UIScreen.main.bounds.width/2;
mySplitViewController.minimumPrimaryColumnWidth = UIScreen.main.bounds.width/2; 
0
grep