Как рисовать одну точку в iOS
Мне было интересно, как лучше всего нарисовать одну точку?
Моя цель - нарисовать эту строку в tableViewCell, чтобы она выглядела так же, как собственный разделитель ячеек.
Я не хочу использовать собственный разделитель, потому что хочу сделать другой цвет и в другом положении (не внизу..).
Сначала я использовал 1px UIView и окрасил его в серый цвет. Но на дисплеях Retina это выглядит как 2px.
Также попытался использовать этот метод:
- (void)drawLine:(CGPoint)startPoint endPoint:(CGPoint)endPoint inColor:(UIColor *)color {
CGMutablePathRef straightLinePath = CGPathCreateMutable();
CGPathMoveToPoint(straightLinePath, NULL, startPoint.x, startPoint.y);
CGPathAddLineToPoint(straightLinePath, NULL, endPoint.x, endPoint.y);
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.path = straightLinePath;
UIColor *fillColor = color;
shapeLayer.fillColor = fillColor.CGColor;
UIColor *strokeColor = color;
shapeLayer.strokeColor = strokeColor.CGColor;
shapeLayer.lineWidth = 0.5f;
shapeLayer.fillRule = kCAFillRuleNonZero;
[self.layer addSublayer:shapeLayer];
}
По какой-то причине он работает примерно в 60% случаев. Что-то не так с ним?
Во всяком случае, я был бы рад услышать о лучшем способе.
Спасибо.
Ответы
Ответ 1
Я сделал то же самое с категорией UIView
. Вот мои методы:
#define SEPARATOR_HEIGHT 0.5
- (void)addSeparatorLinesWithColor:(UIColor *)color
{
[self addSeparatorLinesWithColor:color edgeInset:UIEdgeInsetsZero];
}
- (void)addSeparatorLinesWithColor:(UIColor *)color edgeInset:(UIEdgeInsets)edgeInset
{
UIView *topSeparatorView = [[UIView alloc] initWithFrame:CGRectMake(edgeInset.left, - SEPARATOR_HEIGHT, self.frame.size.width - edgeInset.left - edgeInset.right, SEPARATOR_HEIGHT)];
[topSeparatorView setBackgroundColor:color];
[self addSubview:topSeparatorView];
UIView *separatorView = [[UIView alloc] initWithFrame:CGRectMake(edgeInset.left, self.frame.size.height + SEPARATOR_HEIGHT, self.frame.size.width - edgeInset.left - edgeInset.right, SEPARATOR_HEIGHT)];
[separatorView setBackgroundColor:color];
[self addSubview:separatorView];
}
Просто чтобы добавить к Реми большой ответ, возможно, даже проще сделать это. Сделать класс UILine.m
@interface UILine:UIView
@end
@implementation UILine
-(id)awakeFromNib
{
// careful, contentScaleFactor does NOT WORK in storyboard during initWithCoder.
// example, float sortaPixel = 1.0/self.contentScaleFactor ... does not work.
// instead, use mainScreen scale which works perfectly:
float sortaPixel = 1.0/[UIScreen mainScreen].scale;
UIView *topSeparatorView = [[UIView alloc] initWithFrame:
CGRectMake(0, 0, self.frame.size.width, sortaPixel)];
topSeparatorView.userInteractionEnabled = NO;
[topSeparatorView setBackgroundColor:self.backgroundColor];
[self addSubview:topSeparatorView];
self.backgroundColor = [UIColor clearColor];
self.userInteractionEnabled = NO;
}
@end
В IB, запустите UIView, щелкните идентификатор инспектора и переименуйте класс в UILine. Установите ширину, которую вы хотите в IB. Установите высоту в 1 или 2 пикселя - просто чтобы вы могли видеть ее в IB. Установите цвет фона, который вы хотите в IB. Когда вы запустите приложение, оно станет 1-пиксельной линией шириной этого цвета. (Наверное, вам не следует подвергать никаким настройкам по умолчанию для автоматической настройки в раскадровке /xib, я не мог заставить его сломаться.) Все готово.
Примечание: вы можете подумать: "Почему не просто изменить размер UIView в коде в awakeFromNib?" Изменение размера просмотров при загрузке в приложении раскадровки проблематично - см. Здесь много вопросов!
Интересный gotchya: скорее всего, вы просто сделаете UIView, скажем, 10 или 20 пикселей на раскадровке, просто чтобы вы могли это увидеть. Конечно, он исчезает в приложении, и вы получаете красивую одну пиксельную линию. Но! обязательно запомните self.userInteractionEnabled = NO
, или он может перехватить ваши другие, скажем, кнопки!
2016 решение! fooobar.com/questions/75169/...
Ответ 2
shapeLayer.lineWidth = 0.5f;
Это распространенная ошибка и причина, по которой это работает только некоторое время. Иногда это будет точно перекрывать пиксели на экране, а иногда это не будет. Способ рисования одноточечной линии, которая всегда работает, состоит в том, чтобы нарисовать прямоугольник с одной точкой на целочисленных границах и заполнить его. Таким образом, он всегда будет точно соответствовать пикселям на экране.
Для преобразования из точек в пиксели, если вы хотите это сделать, используйте коэффициент масштабирования вида.
Таким образом, это всегда будет шириной в один пиксель:
CGContextFillRect(con, CGRectMake(0,0,desiredLength,1.0/self.contentScaleFactor));
Здесь показан снимок экрана, показывающий линию, используемую в качестве разделителя, нарисованную в верхней части каждой ячейки:
![enter image description here]()
В самом представлении таблицы нет разделителей (как показано белым пространством ниже трех существующих ячеек). Я не могу рисовать линию в позиции, длине и цвете, которую вы хотите, но это ваша забота, а не моя.
Ответ 3
Метод AutoLayout:
Я использую простой старый UIView и устанавливаю его ограничение по высоте на 1 в Interface Builder. Привязали его к нижней части с помощью ограничений. Конструктор интерфейсов не позволяет установить ограничение по высоте на 0,5, но вы можете сделать это в коде.
Создайте соединитель для ограничения высоты, затем вызовите это:
// Note: This will be 0.5 on retina screens
self.dividerViewHeightConstraint.constant = 1.0/[UIScreen mainScreen].scale
Работал для меня.
FWIW Я не думаю, что нам нужно больше поддерживать сетки сетчатки. Тем не менее, я все еще использую основной экран для будущего доказательства приложения.
Ответ 4
Вы должны учитывать масштабирование из-за сетчатки и что вы не имеете в виду пиксели экрана. См. Основные графические точки против пикселей.
Ответ 5
Дополнение к Реми Вирину, используя Swift 3.0
Создание класса LineSeparator:
import UIKit
class LineSeparator: UIView {
override func awakeFromNib() {
let sortaPixel: CGFloat = 1.0/UIScreen.main.scale
let topSeparatorView = UIView()
topSeparatorView.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: sortaPixel)
topSeparatorView.isUserInteractionEnabled = false
topSeparatorView.backgroundColor = self.backgroundColor
self.addSubview(topSeparatorView)
self.backgroundColor = UIColor.clear
self.isUserInteractionEnabled = false
}
}