Custom Toolbar in UINavigation Controller - xamarin.ios

I am having trouble understanding what approach to take to customize my own Toolbar in Xamarin.ios. The Navigation controller comes with its own default toolbar but how can i change the height and have my own buttons, background image.
What is the best approach for the above ?

You can create a custom navigationBar as you want .
public class xxxViewController: UIViewController
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
NavigationController.NavigationBar.Hidden = true;
double height = IsiphoneX();
UIView backView = new UIView()
{
BackgroundColor = UIColor.White,
Frame = new CGRect(0,20,UIScreen.MainScreen.Bounds.Width, height),
};
UIButton backBtn = new UIButton() {
Frame = new CGRect(20, height-44, 40, 44),
Font = UIFont.SystemFontOfSize(18),
} ;
backBtn.SetTitle("Back", UIControlState.Normal);
backBtn.SetTitleColor(UIColor.Blue, UIControlState.Normal);
backBtn.AddTarget(this,new Selector("GoBack"),UIControlEvent.TouchUpInside);
UILabel titleLabel = new UILabel() {
Frame=new CGRect(UIScreen.MainScreen.Bounds.Width/2-75, 0,150, height),
Font = UIFont.SystemFontOfSize(20),
Text = "xxx",
TextColor = UIColor.Black,
Lines = 0,
};
UILabel line = new UILabel() {
Frame = new CGRect(0, height, UIScreen.MainScreen.Bounds.Width, 0.5),
BackgroundColor = UIColor.Black,
};
backView.AddSubview(backBtn);
backView.AddSubview(titleLabel);
backView.AddSubview(line);
View.AddSubview(backView);
}
double IsiphoneX()
{
double height = 44;
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
{
if (UIApplication.SharedApplication.Delegate.GetWindow().SafeAreaInsets.Bottom > 0.0)
{
height = 64;
}
}
return height;
}
[Export("GoBack")]
void GoBack()
{
NavigationController.PopViewController(true);
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
NavigationController.NavigationBar.Hidden = false;
}
}
You can set the property of title , backButton and navigationBar as you need (such as text , color ,BackgroundColor ,font e.g.)

Related

Draw Graphics on bitmap

I try to use mouse up and mouse down to draw rectangles on bitmaps. But the problem is that the rectangle always delay one event. For example, I try to draw a rectangle (0,0,50,50) in the first time but there is no rectangle drawing on bitmap. I continues drawing a rect (50,50,100,100) but a rect (0,0,50,50) created (not be the rect (50,50,100,100). If I keep to draw next rects, it always delay like that. Please help me!
This is my code:
Rectangle rect = new Rectangle(0, 0, 0, 0);
int Xmouse;
int Ymouse;
public Form1()
{
InitializeComponent();
pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
this.DoubleBuffered = true;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
Xmouse = e.X;
Ymouse = e.Y;
drawOK = true;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (drawOK)
{
drawOK = false;
rect = new Rectangle(Xmouse * 3676 / 800, Ymouse * 3676 / 800, (e.X - Xmouse) * 3676 / 800, (e.Y - Ymouse) * 3676 / 800);
pictureBox1.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
using (var g = Graphics.FromImage(pictureBox1.Image))
{
using (Pen myPen = new Pen(Color.Black, 6))
{
g.DrawRectangle(myPen, rect);
}
}
}
Try moving your draw method outside of paint into a different sub and call that sub manually from mouse up:
Rectangle rect = new Rectangle(0, 0, 0, 0);
int Xmouse;
int Ymouse;
bool drawOK;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
Xmouse = e.X;
Ymouse = e.Y;
Console.WriteLine("MouseDown({0},{1})", e.X, e.Y);
drawOK = true;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (drawOK)
{
drawOK = false;
Console.WriteLine("MouseUp({0},{1})", e.X, e.Y);
rect = new Rectangle(Xmouse , Ymouse , (e.X - Xmouse) , (e.Y - Ymouse) );
DrawRect();
pictureBox1.Invalidate();
}
}
private void DrawRect()
{
Console.WriteLine("drawing {0}", rect);
using (var g = Graphics.FromImage(pictureBox1.Image))
{
using (Pen myPen = new Pen(Color.Black, 6))
{
g.DrawRectangle(myPen, rect);
}
}
}
private void ClearPic()
{
using (var g = Graphics.FromImage(pictureBox1.Image))
{
using (Brush myPen = Brushes.White)
{
g.Clear(Color.White);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
Image bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.Image = bmp;
ClearPic();
pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint);
pictureBox1.MouseDown += pictureBox1_MouseDown;
pictureBox1.MouseUp += pictureBox1_MouseUp;
}

How can I restrict gestures are working only draw line area itself in Xamarin.Ios

What I have tried is
CAShapeLayer shapeLayer = new CAShapeLayer();
shapeLayer.Path = new CGPath();
shapeLayer.Path.AddLines(new CGPoint [] { startingPoint, endingPoint});
shapeLayer.StrokeColor = UIColor.Blue.CGColor;
shapeLayer.LineWidth = (System.nfloat)3.0;
shapeLayer.FillColor = UIColor.Clear.CGColor;
var width = Math.Abs(latestPoint.X - initioalPoint.X) + initioalPoint.X;
var height = Math.Abs(latestPoint.Y - initioalPoint.Y) + initioalPoint.Y;
var padding = 10;
shapeLayer.Frame = new CGRect(5, 5, width + padding - 2, height + padding - 2);
var view = new UIView();
view.Layer.AddSubLayer(shapeLayer);
CanvasView canvasDrawLine = new CanvasView(subView);
canvasDrawLine.Frame = new CGRect(5, 5, width + padding, height + padding[![enter image description here][1]][1]);
Public Class CanvasView : UIView
{
public CanvasView(drawline)
{
drawLine.ClipsToBounds = true;
var width = Math.Abs(endingPoint.X - initioalPoint.X) + initioalPoint.X;
var height = Math.Abs(endingPoint.Y - initioalPoint.Y) + initioalPoint.Y;
var padding = 10;
drawLine.Frame = new CGRect(5,5, width + padding, height + padding);
this.AddSubview(drawLine);
setUpGestures();
}
}
scrollView.AddSubview(canvasDrawLine );
when I set the width and height of the frame default, my gestures not working properly, for example If I have apply a pan gesture to the draw line even out of the draw line also pan gesture is working.How can I restrict all gestures are working only draw line area.
you can calculate bounds of your area covered by line :
CoreGraphics.CGPoint initialPoint = new CoreGraphics.CGPoint(1, 2);
CoreGraphics.CGPoint latestPoint = new CoreGraphics.CGPoint(1, 2);
var width = Math.Abs(latestPoint.X - initialPoint.X);
var height = Math.Abs(latestPoint.X - initialPoint.X);
var padding = 10;
subView.Frame = new CGRect(0, 0, width+padding, height+padding);
I have created sample code with simple view controller class -- Have assigned red colour to view containing line. And its working perfect. gesture recogniser is working on red part only --where line is.
public partial class ViewController : UIViewController
{
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
CGPoint initioalPoint = new CGPoint(12, 12);
CGPoint latestPoint = new CGPoint(80, 45);
var shapeLayer = new CAShapeLayer();
shapeLayer.Path = new CGPath();
shapeLayer.Path.AddLines(new CGPoint[] { initioalPoint, latestPoint });
shapeLayer.StrokeColor = UIColor.Blue.CGColor;
shapeLayer.LineWidth = (System.nfloat)3.0;
shapeLayer.FillColor = UIColor.Clear.CGColor;
var subView = new UIView();
var width = Math.Abs(latestPoint.X - initioalPoint.X) + initioalPoint.X;
var height = Math.Abs(latestPoint.Y - initioalPoint.Y) + initioalPoint.Y;
var padding = 10;
subView.Frame = new CGRect(5, 5, width + padding, height + padding);
subView.Layer.AddSublayer(shapeLayer);
shapeLayer.Frame = new CGRect(5, 5, width + padding-2, height + padding-2);
subView.BackgroundColor = UIColor.Red;
var mainView = new UIView();
mainView.Frame = new CGRect(40, 40, width + padding+200, height + padding+200);
mainView.AddSubview(subView);
mainView.BackgroundColor = UIColor.Yellow;
this.View.AddSubview(mainView);
UITapGestureRecognizer tap = new UITapGestureRecognizer();
tap.AddTarget((obj) => {new UIAlertView("tapped","",null,"ok",null).Show();});
subView.AddGestureRecognizer(tap);
//UITapGestureRecognizer tap = new UITapGestureRecognizer(() => Console.WriteLine("tap"));
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
///To check if Touch Point is inside Given Polygon::
CGPoint pt1 = new CGPoint(initioalPoint.X - 50, initioalPoint.Y - 50);
CGPoint pt2 = new CGPoint(initioalPoint.X + 50, initioalPoint.Y - 50);
CGPoint pt3 = new CGPoint(latestPoint.X - 50, latestPoint.Y + 50);
CGPoint pt4 = new CGPoint(latestPoint.X + 50, latestPoint.Y + 50);
UIBezierPath path = new UIBezierPath();
path.MoveTo(pt1);
path.AddLineTo(pt2);
path.AddLineTo(pt3);
path.AddLineTo(pt4);
path.AddLineTo(pt1);
if (!path.ContainsPoint(ToucPoint))
return;

Control image placement on JTextPane

I am able to add ImageIcons to a JTextPane, but when I add them they show up in the center of the JTextPane. I can't find a way to control where they are placed on the JTextPane. Can someone please help me with this?
This method is making the JTextPane:
private void loadTextPanel(JPanel contentPane) {
chatLogPanel = new JPanel();
chatLogPanel.setLayout(null);
EmptyBorder eb = new EmptyBorder(new Insets(10, 10, 10, 10));
DefaultStyledDocument document = new DefaultStyledDocument();
chatLog = new JTextPane(document);
chatLog.setEditorKit(new WrapEditorKit());
chatLog.setBorder(eb);
chatLog.setMargin(new Insets(5, 5, 5, 5));
chatLogScrollPane = new JScrollPane(chatLog);
addComponent(chatLogPanel, chatLogScrollPane, 0, 0, 500, 240);
addComponent(contentPane, chatLogPanel, 0, 40, 500, 240);
}
This is the code I'm using to add a string to the Panel:
private static void appendToChatLog(JTextPane tp, String msg, Color c) {
chatLog.setEditable(true);
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
aset = sc.addAttribute(aset, StyleConstants.FontFamily, "Lucida Console");
aset = sc.addAttribute(aset, StyleConstants.Alignment, Integer.valueOf(3));
int len = tp.getDocument().getLength();
tp.setCaretPosition(len);
tp.setCharacterAttributes(aset, false);
tp.replaceSelection(msg);
chatLog.setEditable(false);
}
And this is what I'm currently using to add the image to the JTextPane:
BufferedImage image = generateBufferedImage(message.getImage());
Icon icon = new ImageIcon(image);
StyleContext context = new StyleContext();
StyledDocument document = (StyledDocument) chatLog.getDocument();
Style labelStyle = context.getStyle(StyleContext.DEFAULT_STYLE);
JLabel label = new JLabel(icon);
StyleConstants.setComponent(labelStyle, label);
try {
document.insertString(document.getLength(), "Ignored", labelStyle);
} catch (BadLocationException badLocationException) {
badLocationException.printStackTrace();
}
To insert a component to a JTextPane, and display it like a character, use the insertComponent method.
To insert an Icon instead, use the insertIcon method.
Quite intuitive isn't it ;)

I am using following code of Scaling image in monotouch but it is not maintaining quality of image

public static class ImageHelper
{
public static UIImage Scale (UIImage source, SizeF newSize)
{
UIGraphics.BeginImageContext (newSize);
var context = UIGraphics.GetCurrentContext ();
context.InterpolationQuality=CGInterpolationQuality.High;
context.TranslateCTM (0, newSize.Height);
context.ScaleCTM (1f, -1f);
context.DrawImage (new RectangleF (0, 0, newSize.Width, newSize.Height), source.CGImage);
var scaledImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return scaledImage;
}
public static UIImage Rotate (UIImage image)
{
UIImage res;
using (CGImage imageRef = image.CGImage) {
CGImageAlphaInfo alphaInfo = imageRef.AlphaInfo;
CGColorSpace colorSpaceInfo = CGColorSpace.CreateDeviceRGB ();
if (alphaInfo == CGImageAlphaInfo.None) {
alphaInfo = CGImageAlphaInfo.NoneSkipLast;
}
int width, height;
width = imageRef.Width;
height = imageRef.Height;
int maxSize = Math.Max (width, height);
if (height >= width) {
width = (int)Math.Floor ((double)width * ((double)maxSize / (double)height));
height = maxSize;
} else {
height = (int)Math.Floor ((double)height * ((double)maxSize / (double)width));
width = maxSize;
}
CGBitmapContext bitmap;
if (image.Orientation == UIImageOrientation.Up || image.Orientation == UIImageOrientation.Down) {
bitmap = new CGBitmapContext (IntPtr.Zero, width, height, imageRef.BitsPerComponent, imageRef.BytesPerRow, colorSpaceInfo, alphaInfo);
} else {
bitmap = new CGBitmapContext (IntPtr.Zero, height, width, imageRef.BitsPerComponent, imageRef.BytesPerRow, colorSpaceInfo, alphaInfo);
}
switch (image.Orientation) {
case UIImageOrientation.Left:
bitmap.RotateCTM ((float)Math.PI / 2);
bitmap.TranslateCTM (0, -height);
break;
case UIImageOrientation.Right:
bitmap.RotateCTM (-((float)Math.PI / 2));
bitmap.TranslateCTM (-width, 0);
break;
case UIImageOrientation.Up:
break;
case UIImageOrientation.Down:
bitmap.TranslateCTM (width, height);
bitmap.RotateCTM (-(float)Math.PI);
break;
}
bitmap.DrawImage (new Rectangle (0, 0, width, height), imageRef);
res = UIImage.FromImage (bitmap.ToImage ());
bitmap = null;
}
return res;
}
}
Calling method=> UIImage ScaledImage =ImageHelper.Scale (ImageHelper.Rotate (downloadedImage), new SizeF (270, 260));
Please provide any solution to maintain quality as well as it will scale to required size.
Xamarin's UIImage implementation contains two different Scale() methods
Scale(System.Drawing.SizeF) : UIImage
Scale(System.Drawing.SizeF, float) : UIImage

Change color title UITable static section

I have two UITable static sections in my application with both different headers.
The color of the header must be changed because the custom background.
How can I do this solution like ( link ) in my MonoTouch application?
Because I use static sections, I don't have a UITableViewSource where I can do stuff in.
My solution (thanks to Krumelur)
[Export("tableView:viewForHeaderInSection:")]
UIView GetViewForHeaderInSecion (UITableView tableview, int section)
{
UIView view = new UIView (new RectangleF (0, 0, 300, 0));
view.BackgroundColor = UIColor.Clear;
UILabel label = new UILabel (new RectangleF (15, 5, 300, 25));
label.BackgroundColor = UIColor.Clear;
label.TextColor = UIColor.White;
label.ShadowColor = UIColor.Black;
label.ShadowOffset = new SizeF(0, 1);
label.Font = UIFont.BoldSystemFontOfSize(18);
if (section == 0) {
label.Text = "First section";
} else {
label.Text = "Second section";
}
view.AddSubview(label);
return view;
}
You'll have to export the missing method in your controller. Something like:
[Export("tableView:viewForHeaderInSection:")]
UIView GetViewForHeaderInSection(UITableView tableview, int section
{
// return your UIView with whatever background color here
}
Note that you cannot change the color of the predefined view but have to return an entire view instead.

Resources