I want to draw grid like in first image for all devices & user is allowed to fill path only by dragging on grid as a second image,I have tried lots of stuff but no use of it,please suggest me how should i make?
1 Answers
Key Idea
- First, you need to override
UIView
, so that you got to draw on something. - Second you need to know the
height
&width
prior drawing the whole board. - Third need to maintain a data structure which will keep track where to draw & where not to.
First point is easy, we need to override the UIView
class. We will do most of our task in drawRect
method. For the example purpose say the extended class name is CustomGridView
.
Before discussing point #2 we will discuss #3.
Each grid can be in one of the three states,
- empty (no box drawn around this grid)
- surrounded (box drawn around this grid)
- filled surrounded (box drawn & filled with blue color)
so we will declare an enum
for this three states
typedef enum{
EMPTY_BLOCK = 0,
SURROUNDED_BLOCK,
FILLED_SURROUNDED_BLOCK
}
Now we will keep track of the grid using a 2 dimensional array of numbers as declared follows:
NSMutableArray<NSMutableArray<NSNumber*>*>* gridStructure;
initialise the array with EMPTY_BLOCK
& SURROUNDED_BLOCK
as it is wanted in the grid to be shown. For example say you want a grid of height 5 block & width 4 block. All of the outer block will be SURROUNDED_BLOCK
, then the array should look like this.
1, 1, 1, 1
1, 0, 0, 1
1, 0, 0, 1
1, 0, 0, 1
1, 1, 1, 1
now when ever a user will touch the grid, fill that grid position with FILLED_SURROUNDED_BLOCK
.
Now the most point #2, most tedious thing. in the drawRect
you will be specified with the rect
which will denote the height
& width
of the CustomGridView
. Here you will draw the grids according to the array co-ordinates. You have to split up the entire view into grid_width
*grid_height
spaces. Then according to the 2 dimensional array's value you will do the drawing. For example
if you found EMPTY_BLOCK
then draw nothing and rest of them as follows.
Additional resources:
Add a
UIPangestureRecognizer
to track the user touch path & track the position in the 2 dimensional grid array. After updating the 2 dimensional array grid update the view'sdrawRect
call[self setNeedsDisplay]
.Draw 4 line two represent the
FILLED_SURROUNDED_BLOCK
thing.How to draw a line is answered here
Best of luck.
Upon the above idea, here is a sample implementation
GridView.h
#import <UIKit/UIKit.h>
IB_DESIGNABLE @interface GridView : UIView
@end
GridView.m
#import "GridView.h"
enum GRID_BOX_TYPE
{
GRID_BOX_BLANK = 0,
GRID_BOX_RED,
GRID_BOX_BLUE
};
#define NUMBER_OF_ROWS 5
#define NUMBER_OF_COLS 4
#define GRID_LINE_WIDTH 2
@implementation GridView
{
enum GRID_BOX_TYPE twoDGrid[NUMBER_OF_ROWS][NUMBER_OF_COLS];
CGSize gridSizeRatio;
}
#pragma mark init methods
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self){
//do initialization here
[self commonInitializer];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(self){
//do initialization here
[self commonInitializer];
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// CGContextClearRect(context, rect);
//global settings
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
for(int i=0;i<NUMBER_OF_ROWS;i++)
{
for(int j=0;j<NUMBER_OF_COLS;j++)
{
enum GRID_BOX_TYPE blockType = twoDGrid[i][j];
switch (blockType) {
case GRID_BOX_BLANK :
{
//draw white box
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextStrokeRectWithWidth(context, CGRectMake(j * rect.size.width * gridSizeRatio.width,
i * rect.size.height * gridSizeRatio.height,
rect.size.width * gridSizeRatio.width - GRID_LINE_WIDTH,
rect.size.height * gridSizeRatio.height - GRID_LINE_WIDTH), GRID_LINE_WIDTH);
CGContextDrawPath(context, kCGPathFill);
}
break;
case GRID_BOX_RED:
{
//draw red box
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextStrokeRectWithWidth(context, CGRectMake(j * rect.size.width * gridSizeRatio.width,
i * rect.size.height * gridSizeRatio.height,
rect.size.width * gridSizeRatio.width - GRID_LINE_WIDTH,
rect.size.height * gridSizeRatio.height - GRID_LINE_WIDTH), GRID_LINE_WIDTH);
CGContextDrawPath(context, kCGPathFill);
}
break;
case GRID_BOX_BLUE:
{
//draw blue box
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextStrokeRectWithWidth(context, CGRectMake(j * rect.size.width * gridSizeRatio.width,
i * rect.size.height * gridSizeRatio.height,
rect.size.width * gridSizeRatio.width - GRID_LINE_WIDTH,
rect.size.height * gridSizeRatio.height - GRID_LINE_WIDTH), GRID_LINE_WIDTH);
CGContextDrawPath(context, kCGPathFill);
}
break;
default:
break;
}
}
}
}
#pragma mark private initializer
-(void)commonInitializer
{
twoDGrid[0][0]= GRID_BOX_RED;
twoDGrid[0][1]= GRID_BOX_RED;
twoDGrid[0][2]= GRID_BOX_RED;
twoDGrid[0][3]= GRID_BOX_RED;
twoDGrid[1][0]= GRID_BOX_RED;
twoDGrid[1][1]= GRID_BOX_BLANK;
twoDGrid[1][2]= GRID_BOX_BLANK;
twoDGrid[1][3]= GRID_BOX_RED;
twoDGrid[2][0]= GRID_BOX_RED;
twoDGrid[2][1]= GRID_BOX_BLUE;
twoDGrid[2][2]= GRID_BOX_BLUE;
twoDGrid[2][3]= GRID_BOX_RED;
twoDGrid[3][0]= GRID_BOX_RED;
twoDGrid[3][1]= GRID_BOX_BLANK;
twoDGrid[3][2]= GRID_BOX_BLANK;
twoDGrid[3][3]= GRID_BOX_RED;
twoDGrid[4][0]= GRID_BOX_RED;
twoDGrid[4][1]= GRID_BOX_RED;
twoDGrid[4][2]= GRID_BOX_RED;
twoDGrid[4][3]= GRID_BOX_RED;
gridSizeRatio = CGSizeMake(1.0/NUMBER_OF_COLS, 1.0/NUMBER_OF_ROWS);
}
@end
Preview

- 1
- 1

- 7,484
- 4
- 35
- 44
-
Hey Rahul, I got your concept but will please provide me any sample code for same. – Pooja Borkar Nov 14 '16 at 06:09
-
hey, it's Ratul not Rahul :P, btw please mark the answer as accepted, as it meet your requirement :). – Ratul Sharker Nov 14 '16 at 10:54