I tried to remove the border below the UINavigationBar as described here:
NavigationController.NavigationBar.SetBackgroundImage (new UIImage (), UIBarMetrics.Default);
NavigationController.NavigationBar.ShadowImage = new UIImage ();
In the app delegate I also set a background color:
UINavigationBar.Appearance.BackgroundColor = UIColor.FromRGB (247, 247, 247);
Now the UINavigationBar has no border as desired and also the color of the navigation bar has changed. But now the status bar is completely black not showing anything. I tried to set the style of the status bar in the Info.plist but that didn't helped either.
What I'm doing wrong? Do I have to set the background for the status bar somehow?
Now I tried to do that in a separate project and set the background color of the navigation bar. Here the status bar isn't black but the color for the status bar is gone. Only the navigation bar had a color, but the status bar stayed white. Normally through setting the bar tint color the status bar and the navigation bar should get the same color. E.g.
[[UINavigationBar appearance] setBarTintColor:[UIColor yellowColor]];
Setting the bar tint color didn't had an effect so I set the background color of the navigation bar.
How do I remove the border of the navigation bar and set the status and navigation bar to the same color?
I can't remember where I got this but I think it was in obj-c, it's what I use.
public static class UINavigationBarExtensions
{
public static void RemoveShadowImage(this UINavigationBar navigationBar)
{
foreach (var image in
from subView in navigationBar.Subviews
select subView as UIImageView
into imageView
where imageView != null && imageView.ToString()
.Contains("BarBackground")
from image in imageView.Subviews.OfType<UIImageView>()
.Where(image => Math.Abs(image.Bounds.Height - 0.5) < float.Epsilon)
select image)
image.RemoveFromSuperview();
}
}
Because the other approaches didn't worked as expected I now create an image and set this as background for the navigation bar like so:
UIImage backgroundImage = ImageHelper.ImageWithColor (UINavigationBar.Appearance.BarTintColor, new CGRect (0, 0, 1, 1));
NavigationController.NavigationBar.SetBackgroundImage (backgroundImage, UIBarMetrics.Default);
NavigationController.NavigationBar.ShadowImage = new UIImage ();
and here the ImageHelper class:
using System;
using System.Drawing;
using CoreGraphics;
using Foundation;
using UIKit;
public class ImageHelper
{
public ImageHelper ()
{
}
public static UIImage ImageWithColor(UIColor color, CGRect rect){
CGRect rectangleForImage = new CGRect (0, 0, rect.Width, rect.Height);
UIGraphics.BeginImageContext (rectangleForImage.Size);
CGContext context = UIGraphics.GetCurrentContext ();
context.SetFillColor (color.CGColor);
context.FillRect (rectangleForImage);
UIImage image = UIGraphics.GetImageFromCurrentImageContext ();
UIGraphics.EndImageContext ();
return image;
}
}
Related
Below is the link to Custom Progress Bar What I am looking for is to add Right To Left Layout Property for custom progress bar. Can anyone help me in writing property for Right To Left Layout in C#
Custom Progress Bar
As an option, you can change coordinates of painted shapes in OnPaint method this way:
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
if(this.RightToLeft == System.Windows.Forms.RightToLeft.Yes)
e.Graphics.Transform = new Matrix(-1, 0, 0, 1, Width, 0);
//draw background and progress
e.Graphics.ResetTransform();
//draw image
//draw text
//draw border
}
In following image, you can see a left to right and a right to left progress bar:
I have a listview that uses custom cell colors, but when I set a background image in the listview, the custom cell colors will not appear anymore. I tried to remove the background image temporarily (when assembling the list) and restore it after applying cell colors. This results in no custom colors but shows the background. I would like to combine these 2 listview properties if possible.
My code for setting/removing background image:
list.BackgroundImage = Properties.Resources.bgalpha;
list.BackgroundImage = null;
A part of my code for setting custom cell colors:
for (int i = 0; i < kavels.Count(); i++ )
{
if (list.Items[i].SubItems[1].Text != "0")
{
list.Items[i].UseItemStyleForSubItems = false;
list.Items[i].SubItems[1].BackColor = Color.LightGreen;
}
}
Here are two screenshots:
List view with background: http://i.imgur.com/aHUXAVh.png
List view without background: http://i.imgur.com/sO83wTP.png
I also tried making a PictureBox with a transparent background along with a png image with transparency on top of the ListView, but that also didn't work obviously.
You have two options:
You could overlay a Panel or a PictureBox with a semi-transprent Image. For this to work you would have to make it sit inside the ListView, so that it is the Parent of the overlay.
But that will make the Listview non-clickable. - Another problem with this is that it will slightly color the text, so it won't look quite right.
Or you can set the ListView to OwnerDraw = true and add code to do the drawing yourself.
Here is an example, non-scrolled and scrolled:
Note that the original BackgroundImage shines through the emtpy space to the right.
If you owner-draw a ListView in Details mode you need to code events to draw subitems and headers; note the class level variable to hold the itemHeight; this assumes they all have the same Height .. The other one is need for horizontal scrolling.
int itemHeight = 0; // we need this number!
int itemLeft = 0; // we need this number, too
private void listView1_DrawColumnHeader(object sender,
DrawListViewColumnHeaderEventArgs e)
{
Rectangle R0 = listView1.GetItemRect(0);
itemHeight = R0.Height; // we need this number!
itemLeft = R0.Left; // we need this number too
e.DrawBackground();
e.DrawText();
}
private void listView1_DrawSubItem(object sender,
DrawListViewSubItemEventArgs e)
{
Rectangle rrr = listView1.GetItemRect(e.ItemIndex);
Rectangle rect = e.Bounds;
Rectangle rect0 = new Rectangle(rect.X - itemLeft , itemHeight * e.ItemIndex,
rect.Width, rect.Height);
Image img = listView1.BackgroundImage;
e.Graphics.DrawImage(img, rect, rect0, GraphicsUnit.Pixel);
using (SolidBrush brush = new SolidBrush(e.SubItem.BackColor))
e.Graphics.FillRectangle(brush, rect);
e.DrawText();
}
Here is the code to set the colors in the ListViewItem lvi for the example:
lvi.UseItemStyleForSubItems = false;
lvi.BackColor = Color.FromArgb(66, Color.LightBlue);
lvi.SubItems[1].BackColor = Color.FromArgb(77, Color.LightGreen);
lvi.SubItems[2].BackColor = Color.FromArgb(88, Color.LightPink);
Note that the code assumes your background is one large image and no tiling is involved! Also the code works only if you don't have groups!
ObjectListView -- an open source wrapper around a standard .NET ListView -- provides ImageOverlays and true background images too. They both work with colour cells.
I am trying to create a custom UIButton which extends from UIButtonType.RoundedRect.
My added functionality is working, but there is an issue with the initial rounded border state of my button. The border of my extended button is not drawn until after it has been tapped.
Update (January 24th 2013): Added the result of red background test, as requested by Richard Marskell, which concludes only the label of the button is drawn. BackgroundColor = UIColor.Red;
Below is my source code for creating my custom button.
public class TestView : UIView
{
public TestView(IntPtr p) : base(p) { }
public TestView(RectangleF bounds)
{
Frame = bounds;
BackgroundColor = UIColor.White;
UIButton button1 = new UIButton(UIButtonType.RoundedRect);
button1.Frame = new RectangleF(20,20,100,50);
button1.SetTitle("Button 1", UIControlState.Normal);
AddSubview(button1); // Drawn Correctly
MyButton button2 = new MyButton();
button2.Frame = new RectangleF(20,90,100,50);
button2.SetTitle("Button 2", UIControlState.Normal);
AddSubview(button2); // Only drawn correctly after Tap
// EDIT: Added to test Miguel's theory
UIButton button3 = UIButton.FromType(UIButtonType.RoundedRect);
button3.Frame = new RectangleF(20,160,100,50);
button3.SetTitle("Button 3", UIControlState.Normal);
AddSubview(button3); // Drawn Correctly
}
}
public class MyButton : UIButton
{
public MyButton() : base(UIButtonType.RoundedRect) { }
}
I'm just not sure how to force the border to be drawn correctly on loading of the view.
I don't need a button of type UIButtonType.Custom, as I don't want to style the button myself.
When I debug I the type of MyButton is correctly set to UIButtonType.RoundedRect.
The UIButton base properties of MyButton (button2) match the properties of the UIButton instance (button1).
How can I resolve this issue?
Update (January 31st 2013): Herman Schoenfeld provided a suitable solution for this bug.
This works
public class MyButton : UIButton
{
public MyButton() : base(UIButtonType.RoundedRect) { }
public override RectangleF Frame {
get {
return base.Frame;
}
set {
var temp = TranslatesAutoresizingMaskIntoConstraints;
TranslatesAutoresizingMaskIntoConstraints = false;
var constraints = new [] {
NSLayoutConstraint.Create(this, NSLayoutAttribute.Width, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1.0f, value.Width),
NSLayoutConstraint.Create(this, NSLayoutAttribute.Height, NSLayoutRelation.Equal, null, NSLayoutAttribute.NoAttribute, 1.0f, value.Height)
};
AddConstraints(constraints);
SizeToFit();
RemoveConstraints(constraints);
base.Frame = value;
TranslatesAutoresizingMaskIntoConstraints = temp;
}
}
}
This is only a workaround, it appears to be a bug. The SizeToFit() fixes the issue, the other code maintains the frame.
I have created a simple custom panel using ContainerControl as my base. I've added custom properties to create borders and gradient backgrounds. If I override OnPaint and OnPaintBackground all child controls of the parent inherit the gradient and border styles. As a work around I have used the parents BackgroundImage property which works fine but has a few random quirks. There has to be a better way of approaching this issue but I have found no solution. Are there any Window API functions via Interop or other C# methods to fix this? If so please provide an example.
EDIT! Here is the style being copied (ugly example but makes the point):
EDIT 2! Here is a simple hard-coded ContainerControl without all the properties, designer attributes, etc.
public class Container : ContainerControl
{
protected override void OnPaintBackground( PaintEventArgs e )
{
using ( var brush = new LinearGradientBrush( e.ClipRectangle, Color.Red, Color.Blue, LinearGradientMode.Vertical ) )
{
e.Graphics.FillRectangle( brush, e.ClipRectangle );
}
}
}
If a Label control is created with its BackColor property set to Color.Transparent, it will end up calling its parent's OnPaintBackground() implementation.
If you modify Jon's example like this:
var label = new Label {
Text = "Label",
Location = new Point(20, 50),
BackColor = Color.Transparent
};
Then you will reproduce the issue.
There is an easy workaround, however. The problem comes from the way you're creating the linear gradient brush. Since you're passing e.ClipRectangle to its constructor, the shape of the gradient will vary depending on the control being rendered (container or label). On the other hand, if you pass the ClientRectangle of the container, then the gradient will always have the same shape and the result should be what you're looking for:
protected override void OnPaintBackground(PaintEventArgs e)
{
using (var brush = new LinearGradientBrush(ClientRectangle,
Color.Red, Color.Blue, LinearGradientMode.Vertical)) {
e.Graphics.FillRectangle(brush, e.ClipRectangle);
}
}
The result is:
Initialize the properties on control create/load
Then "INVALIDATE" the control to force a redraw of the control
I can't reproduce this simply on my Windows 7 machine - which suggests it may be one of the properties you've set in the designer. Short but complete program:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
public class GradientContainer : ContainerControl
{
protected override void OnPaintBackground(PaintEventArgs e)
{
using (var brush = new LinearGradientBrush(e.ClipRectangle,
Color.Red, Color.Blue, LinearGradientMode.Vertical))
{
e.Graphics.FillRectangle(brush, e.ClipRectangle);
}
}
}
class Test
{
static void Main()
{
var label = new Label {
Text = "Label",
Location = new Point(20, 50)
};
var container = new GradientContainer {
Size = new Size(200, 200),
Location = new Point(0, 0),
Controls = { label }
};
Form form = new Form {
Controls = { container },
Size = new Size(300, 300)
};
Application.Run(form);
}
}
And the result:
If you take a look at the attached image, is there a way to get the drawing logic for this hover effect from the system renderer of the standard WinForms toolstrip ?
http://imageshack.us/photo/my-images/10/toolstriphovereffect.jpg/
EDIT: Anyway, I've manually implemented this with images, but if anyone comes here with a solution, please post.
Maybe this code helps. It draws red circle with black border around toolstripbutton when mouse is over it.
Set your toolstrip properties:
//Set render mode to professional
myToolStrip.RenderMode = ToolStripRenderMode.Professional;
//Assign new instance of your custom renderer
myToolStrip.Renderer = new MyCustomRenderer();
Custom renderer class:
public class MyCustomRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e)
{
if (!e.Item.Selected)
base.OnRenderButtonBackground(e);
else
{
Rectangle rectangle = new Rectangle(0, 0, e.Item.Size.Width - 1, e.Item.Size.Height - 1);
//Draw red circle
e.Graphics.FillEllipse(Brushes.Red, rectangle);
//Draw black border
e.Graphics.DrawEllipse(Pens.Black, rectangle);
}
}
}