how to set rounded corner for a UITextView? - iphone

how to set rounded corner for a UITextView ?

fist import the file
#import <QuartzCore/QuartzCore.h>
and then set the property of your text view
yourTextViewName.layer.cornerRadius = kCornerRadius;
where kCornerRadius is a constant you set as a radius for corner

Try this it will work for sure
you have to import
QuartzCore/QuartzCore.h
UITextView* txtView = [[UITextView alloc] initWithFrame:CGRectMake(50, 50, 300, 100)];
txtView.layer.cornerRadius = 5.0;
txtView.clipsToBounds = YES;

I define an category class for UITextView in .h:
#interface UITextView (RoundedCorner)
-(void) roundedCornerDefault;
-(void) roundedCornerWithRadius:(CGFloat) radius
borderColor:(CGColorRef) color
borderWidth:(CGFloat) width;
#end
and the implementation class:
#import <QuartzCore/QuartzCore.h>
#import "UITextView+RoundedCorner.h"
#implementation UITextView (RoundedCorner)
-(void) roundedCornerDefault {
[self roundedCornerWithRadius:10
borderColor:[[UIColor grayColor] CGColor]
borderWidth:1];
}
-(void) roundedCornerWithRadius:(CGFloat) radius
borderColor:(CGColorRef) color
borderWidth:(CGFloat) width {
self.layer.cornerRadius = radius;
self.layer.borderColor = color;
self.layer.borderWidth = width;
self.clipsToBounds = YES;
}
#end
Example to use it:
#import "UITextView+RoundedCorner.h"
...
[self.myTextView roundedCornerDefault];

Work for me as below code and step
create textView var
#IBOutlet weak var currentAddressOutlet: KMPlaceholderTextView!
create this function
private func setBorderForTextView() {
self.currentAddressOutlet.layer.borderColor = UIColor.lightGray.cgColor
self.currentAddressOutlet.layer.borderWidth = 0.5
self.currentAddressOutlet.layer.cornerRadius = 5
}
call above function in your viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
setupTable()
setBorderForTextView()
}
Result is here

Related

Indent the text in a UITextField

My question is as simple as the title, but here's a little more:
I have a UITextField, on which I've set the background image. The problem is that the text hugs so closely to it's edge, which is also the edge of the image. I want my text field to look like Apple's, with a bit of horizontal space between the background image and where the text starts.
This is the quickest way I've found without doing any subclasses:
UIView *spacerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
[textfield setLeftViewMode:UITextFieldViewModeAlways];
[textfield setLeftView:spacerView];
In Swift:
let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = UITextFieldViewMode.Always
textField.leftView = spacerView
Swift 5:
let spacerView = UIView(frame:CGRect(x:0, y:0, width:10, height:10))
textField.leftViewMode = .always
textField.leftView = spacerView
You have to subclass and override textRectForBounds: and editingRectForBounds:. Here is a UITextfield subclass with custom background and vertical and horizontal padding:
#interface MyUITextField : UITextField
#property (nonatomic, assign) float verticalPadding;
#property (nonatomic, assign) float horizontalPadding;
#end
#import "MyUITextField.h"
#implementation MyUITextField
#synthesize horizontalPadding, verticalPadding;
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectMake(bounds.origin.x + horizontalPadding, bounds.origin.y + verticalPadding, bounds.size.width - horizontalPadding*2, bounds.size.height - verticalPadding*2);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
#end
Usage:
UIImage *bg = [UIImage imageNamed:#"textfield.png"];
CGRect rect = CGRectMake(0, 0, bg.size.width, bg.size.height);
MyUITextField *textfield = [[[MyUITextField alloc] initWithFrame:rect] autorelease];
textfield.verticalPadding = 10;
textfield.horizontalPadding = 10;
[textfield setBackground:bg];
[textfield setBorderStyle:UITextBorderStyleNone];
[self.view addSubview:textfield];
A good approach to add padding to UITextField is to subclass UITextField , overriding the rectangle methods and adding an edgeInsets property. You can then set the edgeInsets and the UITextField will be drawn accordingly. This will also function correctly with a custom leftView or rightView set.
OSTextField.h
#import <UIKit/UIKit.h>
#interface OSTextField : UITextField
#property (nonatomic, assign) UIEdgeInsets edgeInsets;
#end
OSTextField.m
#import "OSTextField.h"
#implementation OSTextField
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
self.edgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
}
return self;
}
- (CGRect)textRectForBounds:(CGRect)bounds {
return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [super editingRectForBounds:UIEdgeInsetsInsetRect(bounds, self.edgeInsets)];
}
#end
I turned this into a nice little extension for use inside Storyboards:
public extension UITextField {
#IBInspectable public var leftSpacer:CGFloat {
get {
return leftView?.frame.size.width ?? 0
} set {
leftViewMode = .Always
leftView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
}
}
}
My 2 cents:
class PaddedTextField : UITextField {
var insets = UIEdgeInsets.zero
var verticalPadding:CGFloat = 0
var horizontalPadding:CGFloat = 0
override func textRect(forBounds bounds: CGRect) -> CGRect {
return CGRect(x: bounds.origin.x + insets.left, y: bounds.origin.y + insets.top, width: bounds.size.width - (insets.left + insets.right), height: bounds.size.height - (insets.top + insets.bottom));
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return textRect(forBounds: bounds)
}
}
I suggest converting your UITextField to a UITextView and setting the contentInset. For example to indent by 10 spaces:
textview.contentInset=UIEdgeInsetsMake(0, 10, 0, 0);
Sometimes the leftView of the textField is a Apple's magnifying glass image.
If so, you can set an indent like this:
UIView *leftView = textField.leftView;
if (leftView && [leftView isKindOfClass:[UIImageView class]]) {
leftView.contentMode = UIViewContentModeCenter;
leftView.width = 20.0f; //the space you want indented.
}
If you don't want to create #IBOutlet's could simply subclass (answer in Swift):
class PaddedTextField: UITextField {
override func awakeFromNib() {
super.awakeFromNib()
let spacerView = UIView(frame:CGRect(x: 0, y: 0, width: 10, height: 10))
leftViewMode = .always
leftView = spacerView
}
}

How to draw a custom UIView that is just a circle - iPhone app

How would I go about drawing a custom UIView that is literally just a ball (a 2D circle)? Would I just override the drawRect method? And can someone show me the code for drawing a blue circle?
Also, would it be okay to change the frame of that view within the class itself? Or do I need to change the frame from a different class?
(just trying to set up a ball bouncing around)
You could use QuartzCore and do something this --
self.circleView = [[UIView alloc] initWithFrame:CGRectMake(10,20,100,100)];
self.circleView.alpha = 0.5;
self.circleView.layer.cornerRadius = 50; // half the width/height
self.circleView.backgroundColor = [UIColor blueColor];
Would I just override the drawRect
method?
Yes:
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, rect);
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor blueColor] CGColor]));
CGContextFillPath(ctx);
}
Also, would it be okay to change the frame of that view within the class itself?
Ideally not, but you could.
Or do I need to change the frame from a different class?
I'd let the parent control that.
Here is another way by using UIBezierPath (maybe it's too late ^^)
Create a circle and mask UIView with it, as follows:
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
view.backgroundColor = [UIColor blueColor];
CAShapeLayer *shape = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:view.center radius:(view.bounds.size.width / 2) startAngle:0 endAngle:(2 * M_PI) clockwise:YES];
shape.path = path.CGPath;
view.layer.mask = shape;
My contribution with a Swift extension:
extension UIView {
func asCircle() {
self.layer.cornerRadius = self.frame.width / 2;
self.layer.masksToBounds = true
}
}
Just call myView.asCircle()
Swift 3 - custom class, easy to reuse. It uses backgroundColor set in UI builder
import UIKit
#IBDesignable
class CircleBackgroundView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.size.width / 2
layer.masksToBounds = true
}
}
Swift 3 class:
import UIKit
class CircleView: UIView {
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else {return}
context.addEllipse(in: rect)
context.setFillColor(UIColor.blue.cgColor)
context.fillPath()
}
}
Another way of approaching circle (and other shapes) drawing is by using masks.
You draw circles or other shapes by, first, making masks of the shapes you need, second, provide squares of your color and, third, apply masks to those squares of color. You can change either mask or color to get a new custom circle or other shape.
#import <QuartzCore/QuartzCore.h>
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIView *area1;
#property (weak, nonatomic) IBOutlet UIView *area2;
#property (weak, nonatomic) IBOutlet UIView *area3;
#property (weak, nonatomic) IBOutlet UIView *area4;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.area1.backgroundColor = [UIColor blueColor];
[self useMaskFor: self.area1];
self.area2.backgroundColor = [UIColor orangeColor];
[self useMaskFor: self.area2];
self.area3.backgroundColor = [UIColor colorWithRed: 1.0 green: 0.0 blue: 0.5 alpha:1.0];
[self useMaskFor: self.area3];
self.area4.backgroundColor = [UIColor colorWithRed: 1.0 green: 0.0 blue: 0.5 alpha:0.5];
[self useMaskFor: self.area4];
}
- (void)useMaskFor: (UIView *)colorArea {
CALayer *maskLayer = [CALayer layer];
maskLayer.frame = colorArea.bounds;
UIImage *maskImage = [UIImage imageNamed:#"cirMask.png"];
maskLayer.contents = (__bridge id)maskImage.CGImage;
colorArea.layer.mask = maskLayer;
}
#end
Here is the output of the code above:
There's another alternative for lazy people. You can set the layer.cornerRadius key path for your view in the Interface Builder. For example, if your view has a width = height of 48, set layer.cornerRadius = 24:
However, this only works if you have a static size of the view (width/height is fixed) and it's not showing the circle in the interface builder.
Swift 3 - Xcode 8.1
#IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let size:CGFloat = 35.0
myView.bounds = CGRect(x: 0, y: 0, width: size, height: size)
myView.layer.cornerRadius = size / 2
myView.layer.borderWidth = 1
myView.layer.borderColor = UIColor.Gray.cgColor
}

Display a progress bar inside a UITextField object

How can one draw a progressbar inside a UITextField ? I have tested two ways so far.
1. Add a UIProgressView object as a subview of the UITextField object.
UIProgressView* progressView = [[UIProgressView alloc] init];
[aUITextField addSubview:progressView];
progressView.progress = 0.5;
[progressView release];
2. Subclass UITextfield and override drawRect:.
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
[self setBackgroundColor:[UIColor clearColor]];
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
[[UIColor orangeColor] setFill];
[[UIBezierPath bezierPathWithOvalInRect:rect] fill];
}
Both approaches didn't work. Do you see any problem with these approaches? And how can I make this work?
I am not sure adding the UIProgressView as a subview of a UITextField object will be useful as you can't change the frame of the progress view.
Subclassing seems to be the right approach. Here is what I could come up with. Check if it is useful to you.
ProgressField.h
#interface ProgressField : UITextField {
}
#property (nonatomic, assign) CGFloat progress;
#property (nonatomic, retain) UIColor * progressColor;
#end
ProgressField.m
#implementation ProgressField
#synthesize progress;
#synthesize progressColor;
- (void)setProgress:(CGFloat)aProgress {
if ( aProgress < 0.0 || aProgress > 1.0 ) {
return;
}
progress = aProgress;
CGRect progressRect = CGRectZero;
CGSize progressSize = CGSizeMake(progress * CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
progressRect.size = progressSize;
// Create the background image
UIGraphicsBeginImageContext(self.bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
CGContextFillRect(context, self.bounds);
CGContextSetFillColorWithColor(context, [self progressColor].CGColor);
CGContextFillRect(context, progressRect);
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[super setBackground:image];
}
- (void)setBackground:(UIImage *)background {
// NO-OP
}
- (UIImage *)background {
return nil;
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
[self setBorderStyle:UITextBorderStyleBezel];
}
return self;
}
This doesn't seem to work with UITextFields with borderStyle set to UITextBorderStyleRoundedRect.
UIProgressView* progressView = [[UIProgressView alloc] init];
progressView.frame = aUITextField.frame;// you can give even set the frame of your own using CGRectMake();
[aUITextField addSubview:progressView];
progressView.progress = 0.5;
[progressView release];
Set the progressview's frame.
Here I think you have to add progressView as subview to self.view , just set progressView's frame according to size that will fit in to UITextField , and make set center of progressview to center of UITextField .
hope it will help you.

UITextView ruled line background but wrong line height

I have a UITextView where the user can create notes and save into a plist file.
I want to be able to show lines just like a normal notebook. The problem I have is
that the text won't align properly.
The image below explains the problem quite well.
This is the background I use to create the lines like the Notes.app
This is my code for creating the background for my UITextView:
textView.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:19.0];
textView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: #"Notes.png"]];
I know that the UIFont.lineHeight property is only available in > iOS 4.x.
So I wonder if there is another solution to my problem?
You should try and draw your lines programmatically rather than using an image. Here's some sample code of how you could accomplish that. You can subclass UITextView and override it's drawRect: method.
NoteView.h
#import <UIKit/UIKit.h>
#interface NoteView : UITextView <UITextViewDelegate> {
}
#end
NoteView.m
#import "NoteView.h"
#implementation NoteView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithRed:1.0f green:1.0f blue:0.6f alpha:1.0f];
self.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:19];
}
return self;
}
- (void)drawRect:(CGRect)rect {
//Get the current drawing context
CGContextRef context = UIGraphicsGetCurrentContext();
//Set the line color and width
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.2f].CGColor);
CGContextSetLineWidth(context, 1.0f);
//Start a new Path
CGContextBeginPath(context);
//Find the number of lines in our textView + add a bit more height to draw lines in the empty part of the view
NSUInteger numberOfLines = (self.contentSize.height + self.bounds.size.height) / self.font.leading;
//Set the line offset from the baseline. (I'm sure there's a concrete way to calculate this.)
CGFloat baselineOffset = 6.0f;
//iterate over numberOfLines and draw each line
for (int x = 0; x < numberOfLines; x++) {
//0.5f offset lines up line with pixel boundary
CGContextMoveToPoint(context, self.bounds.origin.x, self.font.leading*x + 0.5f + baselineOffset);
CGContextAddLineToPoint(context, self.bounds.size.width, self.font.leading*x + 0.5f + baselineOffset);
}
//Close our Path and Stroke (draw) it
CGContextClosePath(context);
CGContextStrokePath(context);
}
#end
MyViewController.h
#import <UIKit/UIKit.h>
#import "NoteView.h"
#interface MyViewController : UIViewController <UITextViewDelegate> {
NoteView *note;
}
#property (nonatomic, retain) NoteView *note;
#end
MyViewController.m
#import "MyViewController.h"
#import "NoteView.h"
#define KEYBOARD_HEIGHT 216
#implementation MyViewController
#synthesize note;
- (void)loadView {
[super loadView];
self.note = [[[NoteView alloc] initWithFrame:self.view.bounds] autorelease];
[self.view addSubview:note];
note.delegate = self;
note.text = #"This is the first line.\nThis is the second line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\nThis is the ... line.\n";
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[note setNeedsDisplay];
}
- (void)textViewDidBeginEditing:(UITextView *)textView {
CGRect frame = self.view.bounds;
frame.size.height -= KEYBOARD_HEIGHT;
note.frame = frame;
}
- (void)textViewDidEndEditing:(UITextView *)textView {
note.frame = self.view.bounds;
}
- (void)dealloc {
[note release];
[super dealloc];
}
Take a look at Apple's documentation for Managing the Keyboard, specifically "Moving Content That Is Located Under the Keyboard". It explains how to listen for NSNotifcations and adjust your views properly.
I think the problem is with your image, the yellow space over the line is creating the problem.
You should edit the image.
And nice work.

How can I change the color of pagination dots of UIPageControl?

I am developing an application in which I want to change either color or image of UIPageControl pagination dots. How can I change it? Is it possible to customize UIpageControl on above scenario?
UPDATE:
This answer is 6 years old and very outdated, but it's still attracting votes and comments. Ever since iOS 6.0 you should be using the pageIndicatorTintColor and currentPageIndicatorTintColor properties on UIPageControl.
ORIGINAL ANSWER:
I ran into this problem today and decided to write my own simple replacement class.
It's a sublassed UIView that uses Core Graphics to render the dots in the colors you specify.
You use the exposed properties to customize and control it.
If you want to you can register a delegate object to get notifications when the user taps on one of the little page dots. If no delegate is registered then the view will not react to touch input.
It's completely fresh from the oven, but seems to work. Let me know if you run into any problems with it.
Future improvements:
Resize the dots to fit the current
bounds if there are too many.
Don't redraw the entire view in drawRect:
Example use:
CGRect f = CGRectMake(0, 0, 320, 20);
PageControl *pageControl = [[[PageControl alloc] initWithFrame:f] autorelease];
pageControl.numberOfPages = 10;
pageControl.currentPage = 5;
pageControl.delegate = self;
[self addSubview:pageControl];
Header file:
//
// PageControl.h
//
// Replacement for UIPageControl because that one only supports white dots.
//
// Created by Morten Heiberg <morten#heiberg.net> on November 1, 2010.
//
#import <UIKit/UIKit.h>
#protocol PageControlDelegate;
#interface PageControl : UIView
{
#private
NSInteger _currentPage;
NSInteger _numberOfPages;
UIColor *dotColorCurrentPage;
UIColor *dotColorOtherPage;
NSObject<PageControlDelegate> *delegate;
//If ARC use __unsafe_unretained id delegate;
}
// Set these to control the PageControl.
#property (nonatomic) NSInteger currentPage;
#property (nonatomic) NSInteger numberOfPages;
// Customize these as well as the backgroundColor property.
#property (nonatomic, retain) UIColor *dotColorCurrentPage;
#property (nonatomic, retain) UIColor *dotColorOtherPage;
// Optional delegate for callbacks when user taps a page dot.
#property (nonatomic, retain) NSObject<PageControlDelegate> *delegate;
#end
#protocol PageControlDelegate<NSObject>
#optional
- (void)pageControlPageDidChange:(PageControl *)pageControl;
#end
Implementation file:
//
// PageControl.m
//
// Replacement for UIPageControl because that one only supports white dots.
//
// Created by Morten Heiberg <morten#heiberg.net> on November 1, 2010.
//
#import "PageControl.h"
// Tweak these or make them dynamic.
#define kDotDiameter 7.0
#define kDotSpacer 7.0
#implementation PageControl
#synthesize dotColorCurrentPage;
#synthesize dotColorOtherPage;
#synthesize delegate;
- (NSInteger)currentPage
{
return _currentPage;
}
- (void)setCurrentPage:(NSInteger)page
{
_currentPage = MIN(MAX(0, page), _numberOfPages-1);
[self setNeedsDisplay];
}
- (NSInteger)numberOfPages
{
return _numberOfPages;
}
- (void)setNumberOfPages:(NSInteger)pages
{
_numberOfPages = MAX(0, pages);
_currentPage = MIN(MAX(0, _currentPage), _numberOfPages-1);
[self setNeedsDisplay];
}
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
// Default colors.
self.backgroundColor = [UIColor clearColor];
self.dotColorCurrentPage = [UIColor blackColor];
self.dotColorOtherPage = [UIColor lightGrayColor];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipedRight:)];
[swipeRight setDirection:UISwipeGestureRecognizerDirectionRight];
[self addGestureRecognizer:swipeRight];
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipedLeft:)];
[swipe setDirection:UISwipeGestureRecognizerDirectionLeft];
[self addGestureRecognizer:swipe];
}
return self;
}
-(void) swipedLeft:(UISwipeGestureRecognizer *) recognizer
{
self.currentPage++;
}
-(void) swipedRight:(UISwipeGestureRecognizer *) recognizer
{
self.currentPage--;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGRect currentBounds = self.bounds;
CGFloat dotsWidth = self.numberOfPages*kDotDiameter + MAX(0, self.numberOfPages-1)*kDotSpacer;
CGFloat x = CGRectGetMidX(currentBounds)-dotsWidth/2;
CGFloat y = CGRectGetMidY(currentBounds)-kDotDiameter/2;
for (int i=0; i<_numberOfPages; i++)
{
CGRect circleRect = CGRectMake(x, y, kDotDiameter, kDotDiameter);
if (i == _currentPage)
{
CGContextSetFillColorWithColor(context, self.dotColorCurrentPage.CGColor);
}
else
{
CGContextSetFillColorWithColor(context, self.dotColorOtherPage.CGColor);
}
CGContextFillEllipseInRect(context, circleRect);
x += kDotDiameter + kDotSpacer;
}
}
- (void)dealloc
{
[dotColorCurrentPage release];
[dotColorOtherPage release];
[delegate release];
[super dealloc];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.delegate) return;
CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];
CGFloat dotSpanX = self.numberOfPages*(kDotDiameter + kDotSpacer);
CGFloat dotSpanY = kDotDiameter + kDotSpacer;
CGRect currentBounds = self.bounds;
CGFloat x = touchPoint.x + dotSpanX/2 - CGRectGetMidX(currentBounds);
CGFloat y = touchPoint.y + dotSpanY/2 - CGRectGetMidY(currentBounds);
if ((x<0) || (x>dotSpanX) || (y<0) || (y>dotSpanY)) return;
self.currentPage = floor(x/(kDotDiameter+kDotSpacer));
if ([self.delegate respondsToSelector:#selector(pageControlPageDidChange:)])
{
[self.delegate pageControlPageDidChange:self];
}
}
#end
In iOS 6 you can set the tint color of UIPageControl:
There are 2 new properties:
pageIndicatorTintColor
currentPageIndicatorTintColor
You can also use the appearance API to change the tint color of all page indicators.
If you are targeting iOS 5 make sure it doesn't crash:
if ([pageControl respondsToSelector:#selector(setPageIndicatorTintColor:)]) {
pageControl.pageIndicatorTintColor = [UIColor whiteColor];
}
pageControl.pageIndicatorTintColor = [UIColor redColor];
pageControl.currentPageIndicatorTintColor = [UIColor redColor];
works for iOS6
In case anyone wants an ARC / modern version of it (no need to redefine properties as ivar, no dealloc, and works with Interface Builder) :
#import <UIKit/UIKit.h>
#protocol PageControlDelegate;
#interface PageControl : UIView
// Set these to control the PageControl.
#property (nonatomic) NSInteger currentPage;
#property (nonatomic) NSInteger numberOfPages;
// Customize these as well as the backgroundColor property.
#property (nonatomic, strong) UIColor *dotColorCurrentPage;
#property (nonatomic, strong) UIColor *dotColorOtherPage;
// Optional delegate for callbacks when user taps a page dot.
#property (nonatomic, weak) NSObject<PageControlDelegate> *delegate;
#end
#protocol PageControlDelegate<NSObject>
#optional
- (void)pageControlPageDidChange:(PageControl *)pageControl;
#end
PageControl.m :
#import "PageControl.h"
// Tweak these or make them dynamic.
#define kDotDiameter 7.0
#define kDotSpacer 7.0
#implementation PageControl
#synthesize dotColorCurrentPage;
#synthesize dotColorOtherPage;
#synthesize currentPage;
#synthesize numberOfPages;
#synthesize delegate;
- (void)setCurrentPage:(NSInteger)page
{
currentPage = MIN(MAX(0, page), self.numberOfPages-1);
[self setNeedsDisplay];
}
- (void)setNumberOfPages:(NSInteger)pages
{
numberOfPages = MAX(0, pages);
currentPage = MIN(MAX(0, self.currentPage), numberOfPages-1);
[self setNeedsDisplay];
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
// Default colors.
self.backgroundColor = [UIColor clearColor];
self.dotColorCurrentPage = [UIColor blackColor];
self.dotColorOtherPage = [UIColor lightGrayColor];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder])
{
self.dotColorCurrentPage = [UIColor blackColor];
self.dotColorOtherPage = [UIColor lightGrayColor];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGRect currentBounds = self.bounds;
CGFloat dotsWidth = self.numberOfPages*kDotDiameter + MAX(0, self.numberOfPages-1)*kDotSpacer;
CGFloat x = CGRectGetMidX(currentBounds)-dotsWidth/2;
CGFloat y = CGRectGetMidY(currentBounds)-kDotDiameter/2;
for (int i=0; i<self.numberOfPages; i++)
{
CGRect circleRect = CGRectMake(x, y, kDotDiameter, kDotDiameter);
if (i == self.currentPage)
{
CGContextSetFillColorWithColor(context, self.dotColorCurrentPage.CGColor);
}
else
{
CGContextSetFillColorWithColor(context, self.dotColorOtherPage.CGColor);
}
CGContextFillEllipseInRect(context, circleRect);
x += kDotDiameter + kDotSpacer;
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.delegate) return;
CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];
CGFloat dotSpanX = self.numberOfPages*(kDotDiameter + kDotSpacer);
CGFloat dotSpanY = kDotDiameter + kDotSpacer;
CGRect currentBounds = self.bounds;
CGFloat x = touchPoint.x + dotSpanX/2 - CGRectGetMidX(currentBounds);
CGFloat y = touchPoint.y + dotSpanY/2 - CGRectGetMidY(currentBounds);
if ((x<0) || (x>dotSpanX) || (y<0) || (y>dotSpanY)) return;
self.currentPage = floor(x/(kDotDiameter+kDotSpacer));
if ([self.delegate respondsToSelector:#selector(pageControlPageDidChange:)])
{
[self.delegate pageControlPageDidChange:self];
}
}
#end
The answer provided by Heiberg works really well, however the page control does not behave exactly like the one by apple.
If you want the page control to behave like the one from apple does (always increment the current page by one if you touch the second half, otherwise decrease by one), try this touchesBegan-method instead:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];
CGRect currentBounds = self.bounds;
CGFloat x = touchPoint.x - CGRectGetMidX(currentBounds);
if(x<0 && self.currentPage>=0){
self.currentPage--;
[self.delegate pageControlPageDidChange:self];
}
else if(x>0 && self.currentPage<self.numberOfPages-1){
self.currentPage++;
[self.delegate pageControlPageDidChange:self];
}
}
Add the following code to DidFinishLauch in AppDelegate,
UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
pageControl.currentPageIndicatorTintColor = [UIColor blackColor];
pageControl.backgroundColor = [UIColor whiteColor];
Hope this will help.
In Swift, this code inside the UIPageViewController is getting a reference to the page indicator and setting its properties
override func viewDidLoad() {
super.viewDidLoad()
//Creating the proxy
let pageControl = UIPageControl.appearance()
//Customizing
pageControl.pageIndicatorTintColor = UIColor.lightGrayColor()
pageControl.currentPageIndicatorTintColor = UIColor.darkGrayColor()
//Setting the background of the view controller so the dots wont be on a black background
self.view.backgroundColor = UIColor.whiteColor()
}
use this for coding
if ([pageControl respondsToSelector:#selector(setPageIndicatorTintColor:)]) {
pageControl.pageIndicatorTintColor = [UIColor whiteColor];
}
or from storyboard you can change from current page tint
Adding to existing answers, it can be done like,
You can fix it with ease by adding the following code to your appdelegate.m file in your didFinishLaunchingWithOptions method:
UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor darkGrayColor];
pageControl.currentPageIndicatorTintColor = [UIColor orangeColor];
pageControl.backgroundColor = [UIColor whiteColor]
This is worked for me in iOS 7.
pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
It's easy with Swift 1.2:
UIPageControl.appearance().pageIndicatorTintColor = UIColor.lightGrayColor()
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor.redColor()
In cased of Swift 2.0 and up, the below code will work:
pageControl.pageIndicatorTintColor = UIColor.whiteColor()
pageControl.currentPageIndicatorTintColor = UIColor.redColor()
#Jasarien I think you can subclass UIPageControll, line picked from apple doc only "Subclasses that customize the appearance of the page control can use this method to resize the page control when the page count changes" for the method sizeForNumberOfPages:
You could also use Three20 Library that contains a styleable PageControl and dozens of other helpful UI Controls and Abstractions.
It's not possible using the iPhone SDK from an official standpoint. You might be able to do it using private methods, but that will be a barrier to getting onto the app store.
The only other safe solution is to create yout own page control which shpuldnt be too difficult given that the page control simply displays what page is currently shown in a scroll view.
myView.superview.tintColor = [UIColor colorWithRed:1.0f
green:1.0f blue:1.0f alpha:1.0f];