iOS tab bar background image propgrammatically - ios

I want to make a separator between items in my tabor programmatically. Then I wrote this code but it display nothing.
float separator_width = 3f;
UIColor separator_color = UIColor.Red;
float itemWidth = (float)Math.Floor(this.TabBar.Frame.Width / this.TabBar.Items.Length);
UIView bgView = new UIView();
bgView.Frame = new CGRect(0, 0, this.TabBar.Frame.Width, this.TabBar.Frame.Height);
for (int i = 0; i < this.TabBar.Items.Length; i++)
{
UIView separator = new UIView();
separator.Frame = new CGRect(itemWidth * (i + 1) - separator_width / 2, 0, separator_width, this.TabBar.Frame.Height);
bgView.Add(separator);
}
UIGraphics.BeginImageContext(new CGSize(bgView.Frame.Width, bgView.Frame.Height));
bgView.Layer.RenderInContext(UIGraphics.GetCurrentContext());
UIImage tabBarBackground = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
UITabBar.Appearance.BackgroundImage = tabBarBackground;
I tried to write it and display it in another view but still nothing. What can I do ?
Thanks

I found another solution. For these who search for that :
Check out below :
var image = new UIImage();
var path = new UIBezierPath();
var lineHeight = 42.5f;
float itemWidth = (float)Math.Floor(this.TabBar.Frame.Width / this.TabBar.Items.Length);
UIGraphics.BeginImageContextWithOptions(new CGSize(this.TabBar.Frame.Width, this.TabBar.Frame.Height), false, 0);
image.Draw(new CGPoint(0,0));
UIColor.Clear.FromHex(0xF2F2F2).SetStroke();
path.LineWidth = 1;
for (int i = 1; i < this.TabBar.Items.Length; i++)
{
path.MoveTo(new CGPoint(itemWidth * i - path.LineWidth / 2, (this.TabBar.Frame.Height - lineHeight) / 2));
path.AddLineTo(new CGPoint(itemWidth * i - path.LineWidth / 2, lineHeight + (this.TabBar.Frame.Height - lineHeight) / 2));
}
path.Stroke();
image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
UITabBar.Appearance.BackgroundImage = image;

Related

Round button with border and shadow

What would be the best way to create a button such as the one in the image?
I tried:
self.button.layer.shadowColor = UIColor.redColor.CGColor;
self.button.layer.shadowRadius = 30.0f;
self.button.layer.shadowOpacity = 1.0f;
self.button.layer.shadowOffset = CGSizeMake(0.0f, 30.0f);
self.button.clipsToBounds = NO;
[self.button setNeedsDisplay];
But this just add a minor very blury shadow not at all like in the image.
Hey #user426132 set UIbutton background image and Try this code
For Objective-c
self.button.layer.cornerRadius = self.button.frame.size.width / 2;
self.button.layer.masksToBounds = false;
self.button.layer.shadowColor = UIColor.grayColor.CGColor;
self.button.layer.shadowOpacity = 1.0;
self.button.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
self.button.layer.shadowRadius = 10;
self.button.layer.shouldRasterize = true;
self.button.layer.rasterizationScale = UIScreen.mainScreen.scale;
For Swift 4.2
self.btnShadow.layer.cornerRadius = self.btnShadow.frame.size.width / 2
self.btnShadow.layer.masksToBounds = false
self.btnShadow.layer.shadowColor = UIColor.black.cgColor
self.btnShadow.layer.shadowOpacity = 1.0
self.btnShadow.layer.shadowOffset = CGSize(width: 0, height: 0)
self.btnShadow.layer.shadowRadius = 10
self.btnShadow.layer.shouldRasterize = true
self.btnShadow.layer.rasterizationScale = UIScreen.main.scale
Output is here in black cross is image

UIProgressView disappear or doesn't scale when device rotate

I am using Xamarin.IOS, I have UIprogressView inside a UIScrollView with two buttons as well.
I am setting the UIprogressView frame by code in ViewWillLayoutSubviews method:
CGRect newFrame;
newFrame.Width = MyScrollView.Frame.Width / 2;
newFrame.Location = new CGPoint(0, NextButton.Frame.Y);
MyProgressView.Frame = newFrame;
MyProgressView.Transform = CGAffineTransform.MakeScale(1, 20f);
MyProgressView.TrackTintColor = CustomColors.CustomColors.GetColor(CustomColors.CustomColors.ColorGray);
MyProgressView.ProgressTintColor = CustomColors.CustomColors.GetColor(CustomColors.CustomColors.ColorBlue);
The problem is when I rotate the device from portrait to landscape, only the progressview will disappear. Meanwhile the next button is there and both progress view and next button have same Y!.
If I stopped using MyProgressView.ProgressTintColor I can see the progress view after rotation but it is not scaled.
Any idea how to fix it?
This is the UIProgressView I am talking about:
Create this UIProgressView file in your Helper folder
LoadingOverlay.cs
public class LoadingOverlay : UIView
{
// control declarations
UIActivityIndicatorView activitySpinner;
UILabel loadingLabel;
public LoadingOverlay(CGRect frame) : base(frame)
{
// configurable bits
BackgroundColor = UIColor.Black;
Alpha = 0.75f;
AutoresizingMask = UIViewAutoresizing.All;
nfloat labelHeight = 22;
nfloat labelWidth = Frame.Width - 20;
// derive the center x and y
nfloat centerX = Frame.Width / 2;
nfloat centerY = Frame.Height / 2;
// create the activity spinner, center it horizontall and put it 5 points above center x
activitySpinner = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.WhiteLarge);
activitySpinner.Frame = new CGRect(
centerX - (activitySpinner.Frame.Width / 2),
centerY - activitySpinner.Frame.Height - 20,
activitySpinner.Frame.Width,
activitySpinner.Frame.Height);
activitySpinner.AutoresizingMask = UIViewAutoresizing.All;
AddSubview(activitySpinner);
activitySpinner.StartAnimating();
// create and configure the "Loading Data" label
loadingLabel = new UILabel(new CGRect(
centerX - (labelWidth / 2),
centerY + 20,
labelWidth,
labelHeight
));
loadingLabel.BackgroundColor = UIColor.Clear;
loadingLabel.TextColor = UIColor.White;
loadingLabel.Text = "Loading Data...";
loadingLabel.TextAlignment = UITextAlignment.Center;
loadingLabel.AutoresizingMask = UIViewAutoresizing.All;
AddSubview(loadingLabel);
}
/// <summary>
/// Fades out the control and then removes it from the super view
/// </summary>
public void Hide()
{
UIView.Animate(
0.5, // duration
() => { Alpha = 0; },
() => { RemoveFromSuperview(); }
);
}
}
and Use this way
to show the loading
var loadingOverlay = new LoadingOverlay(UIScreen.MainScreen.Bounds);
View.Add(loadingOverlay);
and to hide it
loadingOverlay.Hide();
I fixed it by re-scale it at every rotate:
public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
{
progressView.Transform = CGAffineTransform.Scale(progressView.Transform,1, 20f);
}

Core Graphics, odd behaviour with CGContextSetShadowWithColor blur height

I've been adding shadows to my shapes using CGContextSetShadowWithColor. I'm trying to use the same blur offset height.
However the height of the shadow I'm seeing on different shapes is different. I've no idea why this occurring.
Here's some typical code.
CGSize offset = CGSizeMake(0.1, self.l_shadHeight);
CGContextSetShadowWithColor(context, offset, mauveBlurRadius, mauve.CGColor);
EDIT - FURTHER CODE
+ (NSInteger)setShadowHeight
{
NSInteger retVal = 10;
if (IS_IPHONE_6P)
{
retVal = 7;
}
else if (IS_IPHONE_6)
{
retVal = 7;
}
else if (IS_IPHONE_5 || TARGET_INTERFACE_BUILDER)
{
retVal = 6;
}
else if (IS_IPHONE_4_AND_OLDER || IS_IPHONE)
{
retVal = 6;
}
else if (isiPadPro)
{
retVal = 16;
}
else if (IS_IPAD)
{
retVal = 11;
}
return retVal;
}
//
-(void)setSizingClassValues
{
self.l_shadHeight = [DrawingConstants setShadowHeight];
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
[self setSizingClassValues];
//// General Declarations
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
//// Shadow Declarations
//UIColor* circleShadow = shadowColor2;
UIColor* circleShadow = [shadowColor2 colorWithAlphaComponent: [DrawingConstants SHADOW_ALPHA]];
CGSize circleShadowOffset = CGSizeMake(0.1, self.l_shadHeight);
//CGFloat circleShadowBlurRadius = 5;
CGFloat circleShadowBlurRadius = [DrawingConstants setShadowBlurRadius];
//
//// Frames
CGRect frame = self.bounds;
CGFloat xPadding = 18;
CGFloat YPadding = 19;
CGFloat wPadding = 39;
CGFloat hPadding = 54;
if (isiPadPro || IS_IPAD)
{
if (self.size == sizeSmallerPerformance)
{
//so we don't have to rework autolayout on other screens!
CGFloat fac = 2;
xPadding = xPadding / fac;
YPadding = YPadding / fac;
wPadding = wPadding / fac;
hPadding = hPadding / fac;
}
}
//// Subframes
CGRect group = CGRectMake(CGRectGetMinX(frame) + xPadding,
CGRectGetMinY(frame) + YPadding,
CGRectGetWidth(frame) - wPadding,
CGRectGetHeight(frame) - hPadding);
//
//// Abstracted Attributes
CGFloat circleSurroundStrokeWidth = self.l_borderWidth;
CGFloat tongueLeftStrokeWidth = self.l_strokeWidth;;
CGFloat tongueStrokeWidth = self.l_strokeWidth;
//// Group
{
//// CircleSurround Drawing
UIBezierPath* circleSurroundPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(group) + floor(CGRectGetWidth(group) * 0.00164) + 0.5, CGRectGetMinY(group) + floor(CGRectGetHeight(group) * 0.00161) + 0.5, floor(CGRectGetWidth(group) * 0.99836) - floor(CGRectGetWidth(group) * 0.00164), floor(CGRectGetHeight(group) * 0.99839) - floor(CGRectGetHeight(group) * 0.00161))];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, circleShadowOffset, circleShadowBlurRadius, circleShadow.CGColor);
[circleFillColour setFill];
[circleSurroundPath fill];
CGContextRestoreGState(context);
[whiteColour setStroke];
circleSurroundPath.lineWidth = circleSurroundStrokeWidth;
[circleSurroundPath stroke];
}
//// Cleanup
CGGradientRelease(innerFaceGradient);
CGColorSpaceRelease(colorSpace);
}
#end
I've found this issue, I had my shadow on the wrong thing. Instead I added it to my outermost group.
Thanks #kurtrevis

Layout text on the image with Core Text

guys.
I have do rich text eidtor some work with Core Text.I want to keep fixed line height and it truely can be done with the following code:
NSMutableAttributedString *_attributedText = [[NSMutableAttributedString alloc]initWithAttributedString:_attributedString] ;
CGFloat lineSpace=20;
CTParagraphStyleSetting lineSpaceStyle;
lineSpaceStyle.spec=kCTParagraphStyleSpecifierMaximumLineHeight;
lineSpaceStyle.valueSize=sizeof(lineSpace);
lineSpaceStyle.value=&lineSpace;
//CTLineBreakMode lineBreakMode = kCTLineBreakByCharWrapping;
CTParagraphStyleSetting settings[]={
lineSpaceStyle,
// {.spec = kCTParagraphStyleSpecifierLineBreakMode, .valueSize = sizeof(CTLineBreakMode), .value = (const void*)&lineBreakMode},
};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings));
[_attributedText addAttribute:(id)kCTParagraphStyleAttributeName value:(id)paragraphStyle range:NSMakeRange(0, _attributedText.mutableString.length)];
_attributedString = [_attributedText copy];
[_attributedText release];
_attributedText = nil;
CFRelease(paragraphStyle);
Then I want to insert an image into it.And I want type some text on the image with following code:
CTRunDelegateCallbacks callbacks = {
.version = kCTRunDelegateVersion1,
.dealloc = AttachmentRunDelegateDealloc,
.getAscent = AttachmentRunDelegateGetAscent,
.getDescent = AttachmentRunDelegateGetDescent,
.getWidth = AttachmentRunDelegateGetWidth
};
CTRunDelegateRef Rundelegate = CTRunDelegateCreate(&callbacks, [image retain]); //3
NSMutableDictionary *attrDictionaryDelegate = [NSMutableDictionary dictionaryWithDictionary:self.defaultAttributes];
[attrDictionaryDelegate setObject:image
forKey:EGOTextAttachmentAttributeName];
[attrDictionaryDelegate setObject:(id)Rundelegate
forKey:(NSString*)kCTRunDelegateAttributeName];
[attrDictionaryDelegate setObject:fulltext
forKey:EGOTextAttachmentOriginStringKey];
NSAttributedString *newString = [[NSAttributedString alloc] initWithString:EGOTextAttachmentPlaceholderString
attributes:attrDictionaryDelegate];
[attrString replaceCharactersInRange:[result resultByAdjustingRangesWithOffset:attrString.length-astring.length].range
withAttributedString:newString];
In another words,is there some ways to let the text layout on the image with Core Text ?????
Anyone????
Very Easy
keep fixed line height with CoreText,
let the text layout on the image by image.draw(in: frame) ,
maybe frame calculated with CoreText .
here is an example, put a background image below the first word in the line
// here is set up
guard let ctx = UIGraphicsGetCurrentContext(), let f = frameRef else{
return
}
let xHigh = bounds.size.height
ctx.textMatrix = CGAffineTransform.identity
ctx.translateBy(x: 0, y: xHigh)
ctx.scaleBy(x: 1.0, y: -1.0)
guard let lines = CTFrameGetLines(f) as? [CTLine] else{
return
}
// here is an image
let bgGrip = UIImage(named: "grip")
if let pieces = CTLineGetGlyphRuns(line) as? [CTRun]{
let pieceCnt = pieces.count
for i in 0..<pieceCnt{
var p = lineOrigin
if i == 0{
var frame = imageFrame
frame.origin.y = lineOrigin.y + lineAscent - imageHeight + TextContentConst.offsetP.y
bgGrip?.draw(in: frame)
p.x += offsetX
}
ctx.textPosition = p
CTRunDraw(pieces[i], ctx, CFRange(location: 0, length: 0))
}
}

Performance issues when cropping UIImage (CoreGraphics, iOS)

The basic idea of what we are trying to do is that we have a large UIImage, and we want to slice it into several pieces. The user of the function can pass in a number of rows and number of columns, and the image will be cropped accordingly (ie. 3 rows and 3 columns slices the image into 9 pieces). The problem is, we're having performance issues when trying to accomplish this with CoreGraphics. The largest grid we require is 5x5, and it takes several seconds for the operation to complete (which registeres as lagtime to the user.) This is of course far from optimal.
My colleague and I have spent quite a while on this, and have searched the web for answers unsuccessfully. Neither of us are extremely experienced with Core Graphics, so I'm hoping there's some silly mistake in the code that will fix our problems. It's left to you, SO users, to please help us figure it out!
We used the tutorial at http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/ to base revisions of our code on.
The function below:
-(void) getImagesFromImage:(UIImage*)image withRow:(NSInteger)rows withColumn:(NSInteger)columns
{
CGSize imageSize = image.size;
CGFloat xPos = 0.0;
CGFloat yPos = 0.0;
CGFloat width = imageSize.width / columns;
CGFloat height = imageSize.height / rows;
int imageCounter = 0;
//create a context to do our clipping in
UIGraphicsBeginImageContext(CGSizeMake(width, height));
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGRect clippedRect = CGRectMake(0, 0, width, height);
CGContextClipToRect(currentContext, clippedRect);
for(int i = 0; i < rows; i++)
{
xPos = 0.0;
for(int j = 0; j < columns; j++)
{
//create a rect with the size we want to crop the image to
//the X and Y here are zero so we start at the beginning of our
//newly created context
CGRect rect = CGRectMake(xPos, yPos, width, height);
//create a rect equivalent to the full size of the image
//offset the rect by the X and Y we want to start the crop
//from in order to cut off anything before them
CGRect drawRect = CGRectMake(rect.origin.x * -1,
rect.origin.y * -1,
image.size.width,
image.size.height);
//draw the image to our clipped context using our offset rect
CGContextDrawImage(currentContext, drawRect, image.CGImage);
//pull the image from our cropped context
UIImage* croppedImg = UIGraphicsGetImageFromCurrentImageContext();
//PuzzlePiece is a UIView subclass
PuzzlePiece* newPP = [[PuzzlePiece alloc] initWithImageAndFrameAndID:croppedImg :rect :imageCounter];
[slicedImages addObject:newPP];
imageCounter++;
xPos += (width);
}
yPos += (height);
}
//pop the context to get back to the default
UIGraphicsEndImageContext();
}
ANY advice greatly appreciated!!
originalImageView is an IBOutlet ImageView. This image will be cropped.
#import <QuartzCore/QuartzCore.h>
QuartzCore is needed for the white border around each slice for better understanding.
-(UIImage*)getCropImage:(CGRect)cropRect
{
CGImageRef image = CGImageCreateWithImageInRect([originalImageView.image CGImage],cropRect);
UIImage *cropedImage = [UIImage imageWithCGImage:image];
CGImageRelease(image);
return cropedImage;
}
-(void)prepareSlices:(uint)row:(uint)col
{
float flagX = originalImageView.image.size.width / originalImageView.frame.size.width;
float flagY = originalImageView.image.size.height / originalImageView.frame.size.height;
float _width = originalImageView.frame.size.width / col;
float _height = originalImageView.frame.size.height / row;
float _posX = 0.0;
float _posY = 0.0;
for (int i = 1; i <= row * col; i++) {
UIImageView *croppedImageVeiw = [[UIImageView alloc] initWithFrame:CGRectMake(_posX, _posY, _width, _height)];
UIImage *img = [self getCropImage:CGRectMake(_posX * flagX,_posY * flagY, _width * flagX, _height * flagY)];
croppedImageVeiw.image = img;
croppedImageVeiw.layer.borderColor = [[UIColor whiteColor] CGColor];
croppedImageVeiw.layer.borderWidth = 1.0f;
[self.view addSubview:croppedImageVeiw];
[croppedImageVeiw release];
_posX += _width;
if (i % col == 0) {
_posX = 0;
_posY += _height;
}
}
originalImageView.alpha = 0.0;
}
originalImageView.alpha = 0.0; you won't see the originalImageView any more.
Call it like this:
[self prepareSlices:4 :4];
It should make 16 slices addSubView on self.view. We have a puzzle app. This is working code from there.

Resources