web-dev-qa-db-fra.com

Utiliser le style d’indicateur de divulgation de vue tableau pour uibutton ios

J'ai une vue personnalisée et je veux imiter l'indicateur de divulgation trouvé dans les cellules de la vue tableau. Est-ce possible ? Est-il possible d'extraire cette image?

38
VBK

Notez que vous devez utiliser un fond transparent

Voici la meilleure correspondance possible que je puisse obtenir, dans un fichier photoshop:

Notez qu'il inclut la VRAIE IMAGE iOS (à partir d'une capture d'écran) en dessous, en tant que couche, afin que vous puissiez comparer.

http://www.filedropper.com/fakearrowiosnov2013psd


Il semble que VBK souhaite le seul chevron de la collection UITableView. Ce qui s'appelle 'Disclosure Indicator' par opposition à celui disponible chez UIButton qui est 'Detail Disclosure'.

Je pense que vous voulez quelque chose comme ça:

UITableView Disclosure Indicator Image for Buttons

C'est 50x80 avec un fond transparent. Utilisez cette image sur un bouton ou sur UIImageView. Redimensionnez-le à la taille souhaitée pour votre bouton. Apple recommande une cible non moins de 40x40. Je l'ai dimensionné à 10x16 dans mon story-board, mais j'utilise un bouton transparent pour superposer la taille.

Image Mirror: http://imgur.com/X00qn0Z.png


Notez simplement que ceci n'est pas précisément l'image utilisée dans iOS7. (Nov. 2013.) Pour obtenir l'image exacte, lancez simplement une application dans Retina dans votre simulateur et faites une capture d'écran.

12
mevdev

Cela peut être fait entièrement avec du code en plaçant une UITableViewCell avec l'indicateur de divulgation dans une UIButton:

UITableViewCell *disclosure = [[UITableViewCell alloc] init];
disclosure.frame = button.bounds;
disclosure.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
disclosure.userInteractionEnabled = NO; 

[button addSubview:disclosure];

Rapide:

let disclosure = UITableViewCell()
disclosure.frame = button.bounds
disclosure.accessoryType = .disclosureIndicator
disclosure.isUserInteractionEnabled = false

button.addSubview(disclosure)
80
Avario

Puisque Apple fournit des ressources de conception iOS officielles pour différents outils, vous pouvez extraire le chevron à partir de là.

6
fl034

Vous pouvez extraire les images graphiques du simulateur Xcode en utilisant ce projet Xcode - https://github.com/0xced/iOS-Artwork-Extractor

2
Trevor Mayhew

Ce que j'aime faire, c'est de le dessiner avec UIBezierPath. Cela me donne une liberté de redimensionnement si je le souhaite, sans perte de clarté. Et cela me donne également la possibilité de changer de couleur ultérieurement si c'est ce dont j'ai besoin sans éditeur de photos. Le principe est générique et applicable à n'importe quel chemin. L'utilisation est assez simple:

//suppose we want to apply disclosure arrow image to this button:
@IBOutlet weak var btnDisclosure: UIButton!

Tout ce que je dois faire maintenant est:

//get an image from UIBezierPath, resize it for the button and stroke with white:
let arrowImage = UIImage.imageWithBezierPath(UIBezierPath.disclosureArrowPath().scaleToAspectFitRect(CGRect(x: 0, y: 0, width: 22, height: 22)), fillColor: UIColor.clearColor(), strokeColor: UIColor.whiteColor())

//assign disclosure arrow image to the button:
btnDisclosure.setImage(arrowImage, forState: .Normal)

Donc, un morceau de code pour dessiner UIBezierPath qui ressemble à un bouton de divulgation:

extension UIBezierPath
{
    ///Disclosure arrow path. Use scaleToAspectFitRect to resize it to any given rect.
    class func disclosureArrowPath() -> UIBezierPath
    {
        //// arrow Drawing
        let arrowPath = UIBezierPath()
        arrowPath.moveToPoint(CGPointMake(4, 4))
        arrowPath.addLineToPoint(CGPointMake(26.5, 25.24))
        arrowPath.addLineToPoint(CGPointMake(4, 47.5))
        arrowPath.lineWidth = 3

        return arrowPath
    }  

    ///Makes a path scalable to any size.
    ///- parameter newRect: The path will be resized to aspect fit into this rectangle.
    func scaleToAspectFitRect(newRect: CGRect) -> UIBezierPath
    {
        var scaleFactor : CGFloat = 1.0

        //this is probably only the case of scale factor < 1:
        if bounds.width > bounds.height
        {
            //fit witdth:
            scaleFactor = newRect.width/bounds.width
        }
        else
        {
            //fit height:
            scaleFactor = newRect.height/bounds.height
        }

        //scale to aspect fill rect:
        self.applyTransform(CGAffineTransformMakeScale(scaleFactor, scaleFactor))

        return self
    }
}

Ensuite, vous avez besoin d’un moyen d’extraire la UIImage de UIBezierPath. Encore une fois, vous pouvez ajouter une extension à UIImage qui fera ceci comme ceci:

extension UIImage
{
    ///Custom fill and stroke colours for our image based on UIBezierPath
    class func imageWithBezierPath(path: UIBezierPath, fillColor: UIColor, strokeColor: UIColor) -> UIImage
    {
        //enlarge the rect so that stroke line is not clipped:
        let rect = CGRectInset(path.bounds, -path.lineWidth / 2, -path.lineWidth / 2)

        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) //size of the image, opaque, and scale (set to screen default with 0)

        let bezierLayer = CAShapeLayer()
        bezierLayer.path = path.CGPath;
        bezierLayer.fillColor = fillColor.CGColor
        bezierLayer.strokeColor = strokeColor.CGColor
        bezierLayer.lineWidth = path.lineWidth;

        let imgViewTmp = UIImageView(frame: path.bounds)
        imgViewTmp.layer.addSublayer(bezierLayer);
        imgViewTmp.layer.renderInContext(UIGraphicsGetCurrentContext()!)

        let image = UIGraphicsGetImageFromCurrentImageContext()

        //UIGraphicsEndImageContext()
        return image
    }
}

Cela peut sembler excessif pour cette tâche spécifique, mais c'est générique. Et c'est très pratique si vous travaillez beaucoup avec le redimensionnement, essayez de trouver le bon design, etc.

2
Despotovic

Cela a fonctionné pour moi:

UITableViewCell *disclosure = [[UITableViewCell alloc] init];
disclosure.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
for (UIView*v1 in disclosure.subviews)
{
   if ([v1 isKindOfClass:[UIButton class]])
   {
       for (UIView*v2 in v1.subviews)
       {
           if ([v2 isKindOfClass:[UIImageView class]])
           {
               return ((UIImageView*)v2).image;
           }
       }
   }
}
1
sarge

J'ai créé une solution entièrement en code pour dessiner des flèches similaires à l'indicateur de divulgation UITableView.

C'est utilisé comme ça:

let arrowImage = ArrowImageGenerator.generateArrow(withDirection: .down)

La flèche par défaut ressemble à celle par défaut pour l'indicateur de divulgation UITableView . Si vous le souhaitez, vous pouvez personnaliser l'orientation (haut, bas, gauche, droite), la taille, la couleur, etc.

Voici le code:

//
//  ArrowImageGenerator.Swift
//
//  Created by Alessio Orlando on 07/10/15.
//  Copyright © 2015 Alessio Orlando. All rights reserved.
//

import Foundation
import UIKit

enum ArrowDirection {
    case up
    case down
    case left
    case right
}

class ArrowImageGenerator {

    static var defaultColor: UIColor = {
        let color = UIColor(red: 0.783922, green: 0.780392, blue: 0.8, alpha: 1)
        return color
    }()

    class func generateArrow(withDirection direction: ArrowDirection = .right,
                             size: CGSize? = nil,
                             lineWidth: CGFloat = 2.0,
                             arrowColor: UIColor = ArrowImageGenerator.defaultColor,
                             backgroundColor: UIColor = UIColor.clear,
                             scale: CGFloat = UIScreen.main.scale)
        -> UIImage? {

            var actualSize: CGSize
            if let size = size {
                actualSize = size
            }
            else {
                actualSize = defaultSize(for: direction)
            }

            let scaledSize = actualSize.applying(CGAffineTransform(scaleX: scale, y: scale))
            let scaledLineWidth = lineWidth * scale

            UIGraphicsBeginImageContext(CGSize(width: scaledSize.width, height: scaledSize.height))
            defer {
                UIGraphicsEndImageContext()
            }

            guard let context = UIGraphicsGetCurrentContext() else { return nil }
            configureForArrowDrawing(context)

            UIGraphicsPushContext(context)
            strokeArrow(context, size: scaledSize, arrowColor: arrowColor, backgroundColor: backgroundColor, lineWidth: scaledLineWidth, direction: direction)
            UIGraphicsPopContext()

            guard let outputImage = UIGraphicsGetImageFromCurrentImageContext(),
                let quartzImage = context.makeImage() else {
                return nil
            }

            let scaledImage = UIImage(cgImage: quartzImage, scale: scale, orientation: outputImage.imageOrientation)
            return scaledImage
    }

    private class func generateResizableArrow(_ arrowImage: UIImage, direction: ArrowDirection) -> UIImage {
        var edgeInset: UIEdgeInsets?
        switch direction {
        case .up:
            edgeInset = UIEdgeInsets(top: 11, left: 0, bottom: 1, right: 0)
        case .down:
            edgeInset = UIEdgeInsets(top: 1, left: 0, bottom: 11, right: 0)
        case .left:
            edgeInset = UIEdgeInsets(top: 1, left: 11, bottom: 1, right: 0)
        case .right:
            edgeInset = UIEdgeInsets(top: 1, left: 0, bottom: 1, right: 11)
        }
        let resizableImage = arrowImage.resizableImage(withCapInsets: edgeInset!)
        return resizableImage
    }

    private class func configureForArrowDrawing(_ context: CGContext) {
        context.setBlendMode(CGBlendMode.normal)
        context.setAllowsAntialiasing(true)
        context.setShouldAntialias(true)
    }

    private class func strokeArrow(_ context: CGContext, size: CGSize, arrowColor: UIColor, backgroundColor: UIColor, lineWidth: CGFloat = 1.0, direction: ArrowDirection) {
        backgroundColor.setFill()
        UIRectFill(CGRect(Origin: CGPoint(x: 0, y: 0), size: size))
        arrowColor.setStroke()
        context.setLineWidth(lineWidth)
        let lineWidthOffset = lineWidth / 2 // needed to make the arrow pointy.

        switch direction {
        case .up:
            context.move(to: CGPoint(x: size.width, y: size.height))
            context.addLine(to: CGPoint(x: size.width / 2, y: 0 + lineWidthOffset))
            context.addLine(to: CGPoint(x: 0, y: size.height))
        case .down:
            context.move(to: CGPoint(x: size.width, y: 0))
            context.addLine(to: CGPoint(x: size.width / 2, y: size.height - lineWidthOffset))
            context.addLine(to: CGPoint(x: 0, y: 0))
        case .left:
            context.move(to: CGPoint(x: size.width, y: 0))
            context.addLine(to: CGPoint(x: lineWidthOffset, y: size.height / 2))
            context.addLine(to: CGPoint(x: size.width, y: size.height))
        case .right:
            context.move(to: CGPoint(x: 0, y: 0))
            context.addLine(to: CGPoint(x: size.width - lineWidthOffset, y: size.height / 2))
            context.addLine(to: CGPoint(x: 0, y: size.height))
        }
        context.strokePath()
    }

    class func defaultSize(for direction: ArrowDirection) -> CGSize {
        switch direction {
        case .up, .down:
            return CGSize(width: 12, height: 7)
        case .left, .right:
            return CGSize(width: 7, height: 12)
        }
    }
}

Voici le Gist complet: github Gist

1
ale84

Pour Xamarin.iOS

//create your button
var systolicWell = new UIButton(UIButtonType.RoundedRect);
systolicWell.BackgroundColor = UIColor.White;

//create the UITableViewCell
var systolicDisclosure = new UITableViewCell();
systolicDisclosure.Accessory = UITableViewCellAccessory.DisclosureIndicator;
systolicDisclosure.UserInteractionEnabled = false;

//add the button, then the UITableViewCell to the View
View.AddSubviews(systolicWell, systolicDisclosure);

//using FluentLayout https://github.com/slodge/Cirrious.FluentLayout
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();

View.AddConstraints(
                systolicWell.AtTopOf(View).Plus(5),
                systolicWell.Width().EqualTo().WidthOf(View),
                systolicWell.Height().EqualTo(10),

                systolicDisclosure.WithSameTop(systolicWell),
                systolicDisclosure.WithSameWidth(systolicWell),
                systolicDisclosure.WithSameHeight(systolicWell));
0
ben