我有一个自定义视图,我想模仿表格视图单元格中的披露指示符。这可能吗 ?无论如何提取该图像?
11 回答
这可以通过将UITableViewCell
带有披露指示符的 a放在 a 中完全使用代码来完成UIButton
:
UITableViewCell *disclosure = [[UITableViewCell alloc] init];
disclosure.frame = button.bounds;
disclosure.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
disclosure.userInteractionEnabled = NO;
[button addSubview:disclosure];
迅速:
let disclosure = UITableViewCell()
disclosure.frame = button.bounds
disclosure.accessoryType = .disclosureIndicator
disclosure.isUserInteractionEnabled = false
button.addSubview(disclosure)
由于 Apple 为不同的工具提供官方 iOS 设计资源,您可以从那里提取人字形。
更新
Apple在 WWDC'19 主题演讲中宣布了图标字体SF Symbols 。
SF Symbols 配套应用程序包含一个chevron.right
可供您使用的图标。您还可以指定图标的粗细。
请注意,您必须使用透明背景
这是我能得到的最好的匹配,在一个 Photoshop 文件中:
请注意,它在下面包含了 REAL iOS IMAGE(来自屏幕截图)作为图层,因此您可以进行比较。
http://www.filedropper.com/fakearrowiosnov2013psd
似乎 VBK 想要 UITableView 集合中的单个 V 形。这被称为“披露指示器”,而不是 UIButton 提供的“详细信息披露”。
我想你想要这样的东西:
它是 50x80,具有透明背景。在按钮或 UIImageView 上使用此图像。将其调整为您希望按钮的大小。Apple 建议命中目标不少于 40x40。我在情节提要中将其大小设置为 10x16,但我使用的是透明按钮叠加层,因此大小无关紧要。
图片镜像:http: //imgur.com/X00qn0Z.png
但是请注意,这并不完全是 iOS7 中使用的图像。(2013 年 11 月。)要获得准确的图像,只需在您的模拟器中在视网膜中运行一个应用程序,然后制作一个屏幕截图。
我喜欢做的是使用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
}
}
对于这个特定的任务来说,这似乎是一种矫枉过正,但它是通用的。如果你经常处理调整大小、试图找出正确的设计等,这真的很方便。
我制作了一个完全在代码中的解决方案来绘制类似于 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
您可以使用此 Xcode 项目从 Xcode 模拟器中提取图形图像 - https://github.com/0xced/iOS-Artwork-Extractor
这对我有用:
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;
}
}
}
}
斯威夫特 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
}()
纵横比 UIView 扩展
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
}
}
对于 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 / 斯威夫特4:
按钮的披露指示器
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)
}
}
您可以在 UITableViewCell 的右侧添加任何自定义图像,只需一行代码:
尝试这个:
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.accessoryView = [[UIImageView alloc]initWithImage:
[UIImage imageNamed:@"blueButton.png"]];
}