I have a custom view and i want to imitate the disclosure indicator found in table view cells. Is this possible ? Is there anyway of extracting that image ?
-
1great question - it's annoying it's not available! – Fattie Nov 28 '13 at 19:36
-
Here's the best possible match in a photoshop file, with a correct transparent background: http://www.filedropper.com/fakearrowiosnov2013psd – Fattie Nov 29 '13 at 09:11
-
Yup, super dumb that this is already there cause its used in tableviewcell, but you cannot use it elsewhere. Even worse is when apple docs show screenshots using that image. – lostintranslation Jul 21 '14 at 16:38
11 Answers
This can be done entirely with code by placing a UITableViewCell
with the disclosure indicator within a 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)

- 4,655
- 3
- 26
- 19
-
7kind of ugly, but it works and does give the desired effect (OS image), without having to add custom images. +1 – Jeroen Bouma Jan 08 '14 at 13:03
-
2Perhaps a little ugly, but much better than using your own image because forward compatibility. – Josh Liptzin Jan 27 '15 at 19:19
-
8Don't try this in iOS 8 because you will get the following error: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Must translate autoresizing mask into constraints to have _setHostsLayoutEngine:YES.' This happens whenever you add a UITableViewCell or cell subclass to a non-UITableView UIView/UIView subclass. See the related post at: http://stackoverflow.com/questions/24217195/why-do-i-get-must-translate-autoresizing-mask-into-constraints-to-have-sethost – Pat Feb 08 '15 at 19:57
-
3This solution worked for me with 8.1, Swift, and Xcode 6.2. I tried with translatesAutoresizingMaskIntoConstraints as true and false and both were OK. – Andrew Duncan Mar 15 '15 at 04:35
-
@Avario How does this work within cellForRowAtIndexPath? Also any idea as to why this works? I would like to add a disclosure indicator to my non-transparent table view cell, but I must be misunderstanding how to apply this. Thanks for any suggestions. – sunny May 27 '15 at 18:07
-
1@sunny This code is for adding the disclosure indicator to a UIButton. If you just want the disclosure indicator within a normal table view cell, before you return your cell from cellForRowAtIndex path just make sure you set cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator – Avario Jun 08 '15 at 04:03
-
1Did this work for anyone? We aren't seeing anything on our buttons with this code in Xcode 8.3.2 – Praxiteles May 07 '17 at 11:01
-
1
-
I really *really* **really** hate this approach, but it still works on iOS 11 and 12, so whatever. Thanks! – Nick Gaens Apr 08 '19 at 14:03
Since Apple provides official iOS design resources for different tools you can extract the chevron from there.
Update
Apple announced the icon font SF Symbols on the WWDC'19 keynote.
The SF Symbols companion app contains an icon called chevron.right
ready for you to use. You can also Specify the thickness of the icon.

- 5,291
- 3
- 32
- 46
Note that you must use a transparent background
Here's the best possible match I can get, in a photoshop file:
Note that it includes the REAL iOS IMAGE (from a screenshot) underneath as a layer, so you can compare.
http://www.filedropper.com/fakearrowiosnov2013psd
It seems like VBK wants the single chevron from the UITableView collection. Which is called 'Disclosure Indicator' as opposed to the one available from UIButton which is 'Detail Disclosure'.
I think you want something like this:
It is 50x80 with a transparent background. Use this image on top of a button or UIImageView. Resize it to whatever size you'd like your button to be. Apple recommends a hit target of no less than 40x40. I sized it to 10x16 in my storyboard, but I am using a transparent button overlay so the size doesn't matter.
Image Mirror : https://i.stack.imgur.com/tGpTg.png
Just note however this is not precisely the image used in iOS7. (Nov 2013.) To get the exact image, simply run an app in retina in your simulator, and make a screenshot.
-
1great answer -- **it does seem to be the case that you can NOT GET at the image for the arrow in iOS**. many of the questions about this on the site are confused, because people confuse the **DETAIL** disclosure icon (that is the stupid, useless, "help symbol" icon). For example this answer on rotation is superb, BUT, unfortunately it is only relevant t the useless "disclosure" icon .. http://stackoverflow.com/questions/11222042/how-to-rotate-uitableviewcellaccessorydisclosureindicator mevdev is correct (2013) that you just have to use a PNG. I call it fakeArrow.png :) – Fattie Nov 29 '13 at 07:38
What I like to do is to draw it using UIBezierPath
. This gives me a freedom to resize if I want to, without loosing clarity. And it also gives me an opportunity to change the colour later on if that's what I need without a photo editor.The principle is generic and applicable to any given path. The usage is quite simple:
//suppose we want to apply disclosure arrow image to this button:
@IBOutlet weak var btnDisclosure: UIButton!
All I need to do now is:
//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)
So, a piece of code for drawing the UIBezierPath which looks like disclosure button:
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
}
}
Next, you need a way to get the UIImage
out of UIBezierPath
. Again, you could add extension to UIImage that will do this like so:
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
}
}
It may seem as an overkill for this specific task, but it's generic. And it's really handy if you deal a lot with resizing, trying to figure out the right design etc.

- 1,807
- 2
- 20
- 24
I made an entirely in code solution to draw arrows similar to UITableView disclosure indicator.
It's used like this:
let arrowImage = ArrowImageGenerator.generateArrow(withDirection: .down)
The default arrow looks the same as the default for the UITableView disclosure indicator. If you want you can customize direction (up, down, left, right), size, color and so on.
Here is the 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)
}
}
}
Here is the complete gist: github gist

- 1,406
- 12
- 16
You can extract the graphic images from the Xcode Simulator using this Xcode project - https://github.com/0xced/iOS-Artwork-Extractor

- 21
- 4
This worked for me:
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;
}
}
}
}

- 183
- 2
- 6
SWIFT 5
private lazy var iconImageView: UIImageView = {
let imageView = UIImageView()
let configuration = UIImage.SymbolConfiguration(pointSize: 13, weight: .medium)
imageView.image = UIImage(systemName: "chevron.right", withConfiguration: configuration)
imageView.tintColor = .lightGray
imageView.contentMode = .scaleAspectFit
imageView.constrainAspectRatio(17.0/10.0)
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
Aspect Ratio UIView Extension
extension UIView {
/// Ratio height/width. Example: 20/40 (20 is height, 40 is width)
func constrainAspectRatio(_ ratio: CGFloat) {
NSLayoutConstraint(item: self,
attribute: .height,
relatedBy: .equal,
toItem: self,
attribute: .width,
multiplier: ratio,
constant: 0).isActive = true
}
}

- 772
- 1
- 21
- 31
For 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));

- 3,126
- 3
- 37
- 51
Swift3 / Swift4:
disclosure indicator for button
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)
add this extension for CGRect
extension CGRect {
init(_ x:CGFloat, _ y:CGFloat, _ w:CGFloat, _ h:CGFloat) {
self.init(x:x, y:y, width:w, height:h)
}
}

- 11
- 5
You can add any custom image on the right side of UITableViewCell with a single line of Code:
Try This:
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.accessoryView = [[UIImageView alloc]initWithImage:
[UIImage imageNamed:@"blueButton.png"]];
}

- 64
- 7
-
Sometimes it is a good idea to read the question twice before providing an answer. I did not downvote though.... – eharo2 Feb 25 '19 at 21:46