Используйте стиль индикатора раскрытия таблицы для uibutton ios

У меня есть пользовательский вид, и я хочу подражать индикатору раскрытия, найденному в ячейках таблицы. Это возможно? Есть ли способ извлечь это изображение?

Ответ 1

Обратите внимание, что вы должны использовать прозрачный фон

Здесь наилучшее совпадение, которое я могу получить, в файле photoshop:

Обратите внимание, что он включает REAL iOS IMAGE (снимок экрана) под слоем, поэтому вы можете сравнить.

http://www.filedropper.com/fakearrowiosnov2013psd


Кажется, что VBK хочет получить единственный шеврон из коллекции UITableView. Это называется индикатором раскрытия информации, в отличие от того, который доступен в UIButton, который является "Подробным раскрытием".

Я думаю, вам нужно что-то вроде этого:

UITableView Disclosure Indicator Image for Buttons

Это 50x80 с прозрачным фоном. Используйте это изображение поверх кнопки или UIImageView. Измените его размер независимо от того, какой размер вы хотите использовать. Apple рекомендует поразить цель не менее 40x40. Я оценил его до 10x16 в своем раскадровке, но я использую прозрачную наложенную кнопку, поэтому размер не имеет значения.

Зеркало изображения: http://imgur.com/X00qn0Z.png


Просто обратите внимание, что это не совсем изображение, используемое в iOS7. (Ноябрь 2013 г.) Чтобы получить точный образ, просто запустите приложение в сетчатке на вашем симуляторе и сделайте снимок экрана.

Ответ 2

Это можно сделать полностью с кодом, поместив UITableViewCell с индикатором раскрытия в пределах UIButton:

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

[button addSubview:disclosure];

Swift:

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

button.addSubview(disclosure)

Ответ 3

Поскольку Apple предоставляет официальные ресурсы iOS для различных инструментов, вы можете извлечь шеврон оттуда.


Обновить

Apple анонсировала иконку шрифта SF Symbols на лейтмотиве WWDC'19.

Сопутствующее приложение SF Symbols содержит значок chevron.right готовый для использования. Вы также можете указать толщину значка.

enter image description here

Ответ 4

Мне нравится делать это с помощью UIBezierPath. Это дает мне свободу изменять размер, если я хочу, без потери ясности. И это также дает мне возможность изменить цвет позже, если это то, что мне нужно без редактора фотографий. Этот принцип является общим и применимым к любому пути. Использование довольно просто:

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

Теперь мне нужно сделать следующее:

//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)

Итак, фрагмент кода для рисования UIBezierPath, который выглядит как кнопка раскрытия:

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
    }
}

Далее вам нужно получить UIImage из UIBezierPath. Опять же, вы можете добавить расширение к UIImage, которое сделает это следующим образом:

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
    }
}

Это может показаться излишним для этой конкретной задачи, но это общий. И это действительно удобно, если вы много делаете с изменением размера, пытаясь понять правильный дизайн и т.д.

Ответ 6

Это сработало для меня:

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;
           }
       }
   }
}

Ответ 7

Я сделал полностью в коде решение, чтобы нарисовать стрелки, похожие на индикатор раскрытия UITableView.

Используется так:

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

Стрелка по умолчанию выглядит так же, как и по умолчанию для индикатора раскрытия UITableView. Если вы хотите, вы можете настроить направление (вверх, вниз, влево, вправо), размер, цвет и так далее.

Вот код:

//
//  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)
        }
    }
}

Вот полный смысл: github gist

Ответ 8

Для 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));

Ответ 9

Swift3/Swift4:

индикатор раскрытия для кнопки

        let disclosureIndicator = UITableViewCell(style: .value1, 
        reuseIdentifier: nil)
        let theWidth = UIScreen.main.bounds.width
        let theHeight = yourButton.frame.height
        yourButton.frame = CGRect(0,0, theWidth, theHeight)
        disclosureIndicator.textLabel?.text = "title"
        disclosureIndicator.detailTextLabel?.textColor = .black
        disclosureIndicator.detailTextLabel?.text = "subtitle"
        disclosureIndicator.accessoryType = .disclosureIndicator
        disclosureIndicator.isUserInteractionEnabled = false
        disclosureIndicator.frame = yourButton.bounds

        yourButton.addSubview(disclosureIndicator)

добавить это расширение для CGRect

extension CGRect {
    init(_ x:CGFloat, _ y:CGFloat, _ w:CGFloat, _ h:CGFloat) {
        self.init(x:x, y:y, width:w, height:h)
    }
}

Ответ 10

Вы можете добавить любое пользовательское изображение с правой стороны UITableViewCell с помощью одной строки кода:

Попробуйте следующее:

-(UITableViewCell *)tableView:(UITableView *)tableView 
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    cell.accessoryView = [[UIImageView alloc]initWithImage:
    [UIImage imageNamed:@"blueButton.png"]];
}