A rectangle in Xamarin.Android - xamarin.android

How can I draw or put a Rectangle in Xamarin.Android(in Visual Studio) by designer(Main.axml) or from code or Strings.xml file ?

There are several ways to approach this.
Use a Drawable xml file where you define a rectangle.
Use a 9-patch image representing a rectangle.
Use an image showing a rectangle.
Create a custom View where you override the OnDraw method and draw the rectangle there.
For 1. you can do something like:
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#ffffff"/>
<size android:height="20dp" />
</shape>
and then use it for the background in a View when you define it in an layout file.
For the last approach you can do something like:
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Views;
using Android.OS;
namespace AndroidApplication2
{
[Activity(Label = "AndroidApplication2", MainLauncher = true, Icon = "#drawable/icon")]
public class Activity1 : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var rectView = new RectangleView(this);
SetContentView(rectView);
}
}
public class RectangleView : View
{
public RectangleView(Context context)
: base(context) { }
protected override void OnDraw(Canvas canvas)
{
var paint = new Paint {Color = Color.Blue, StrokeWidth = 3};
canvas.DrawRect(30, 30, 80, 80, paint);
}
}
}

Related

How to fix WebView layout in Xamarin Forms after rotation on iOS (WKWebView)

I'm encountering problems getting a WebView to take up the whole screen properly in an iOS app using Xamarin Forms 4.8.0.1364 & in a ContentPage. The native control is WkWebView and am testing in an iPhone 12, iOS 14.1 Simulator.
Also, when the device rotates back into portrait orientation, the size of the WebView is wrong, or the content in the WebView is rendered improperly.
The XAML is as follows(note the BackgroundColor relative to the screencaps):
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewModel="clr-namespace:MyCompany.MyApp.ViewModels;assembly=MyAssembly"
x:Class="MyCompany.MyApp.Views.MyWebViewPage"
BackgroundColor="Green" >
<ContentPage.BindingContext>
<viewModel:MyPageViewModel URL="https://login.somepage.com" />
</ContentPage.BindingContext>
<ContentPage.Content>
<Grid BackgroundColor="Blue">
<WebView x:Name="WebView"
BackgroundColor="Black"
Source="{Binding URL}"
Cookies="{Binding Cookies}">
</WebView>
</Grid>
</ContentPage.Content>
</ContentPage>
Note: I've tried a lot of things and have removed everything that didn't make a difference. Have tried FillAndExpand on HorizontalOptions and VerticalOptions, as well as Star and Auto sizing on Grid columns/rows. I removed everything that didn't make a difference from the XAML.
The results are:
Original Portrait(good enough!):
After rotating 90 to landscape:
After rotating back to portrait(content issue?):
What I would like to see is the WebView taking up the whole screen w/ none of the various colors visible(Green, Blue, Black), and after rotation, the content should fit as expected.
I have also tried a Custom Renderer.
public class MyWebViewRenderer : WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
}
}
public override void LayoutSubviews()
{
Bounds = CalculateBounds();
base.LayoutSubviews();
}
private CGRect CalculateBounds()
{
var screenBounds = UIScreen.MainScreen.Bounds;
var statusBarHeight = UIApplication.SharedApplication.StatusBarFrame.Height;
nfloat navBarHeight = 0;
var uiNavController = Window?.RootViewController as UINavigationController;
if (uiNavController?.TopViewController != null)
{
navBarHeight = uiNavController.NavigationBar.Bounds.Height;
}
var adjustedHeight = statusBarHeight + navBarHeight;
var bounds = new CGRect(screenBounds.X, screenBounds.Y + adjustedHeight,
screenBounds.Width, screenBounds.Height - adjustedHeight);
return bounds;
}
}
The results when calculating bounds in MyWebViewRenderer.LayoutSubviews, the results are:
Initial page load in Portrait mode:
(my height calculation is off?)
After rotate to landscape(looks ok actually):
After rotate back to portrait, the height calc is ok but somehow it's offset:
Any suggestions?
Thanks
Set the width of the page to follow the screen-width of the device and VerticalOptions to FillAndExpand. See also this answer:
using Foundation;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using MyNamespace.iOS.Renderers;
[assembly: ExportRenderer(typeof(WebView), typeof(MyWebViewRenderer))]
namespace MyNamespace.iOS.Renderers
{
public class MyWebViewRenderer : WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
WebView webView = Element as WebView;
webView.VerticalOptions = LayoutOptions.FillAndExpand;
//width=device-width sets the width of the page to follow the screen-width of the device
string jScript = #"" +
"var meta = document.createElement('meta'); " +
"meta.setAttribute('name', 'viewport');" +
"meta.setAttribute('content', 'width=device-width');" +
"document.getElementsByTagName('head')[0].appendChild(meta);";
var userScript = new WKUserScript((NSString)jScript, WKUserScriptInjectionTime.AtDocumentEnd, true);
this.Configuration.UserContentController.AddUserScript(userScript);
}
}
}
}
Have a try to use WKUserScript to ensure the webpag was displayed with the same size as the screen size:
public class MyWebViewRenderer : WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
string jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
WKUserScript wkUScript = new WKUserScript(new NSString(jScript),WKUserScriptInjectionTime.AtDocumentEnd,true);
WKUserContentController wkUController = new WKUserContentController();
wkUController.AddUserScript(wkUScript);
WKWebViewConfiguration webConfig = new WKWebViewConfiguration();
this.Configuration.UserContentController = wkUController;
}
}
}

Self Size Custom View from xib in Stack view in Xamarin iOS

I'm new at Xamarin development and I'm trying to display the list of comments for a specific ticket. The comments' body have different text size. I have a custom view TicketCommentRowUIView.xib:
using Foundation;
using System;
using UIKit;
using ObjCRuntime;
namespace Project.iOS
{
public partial class TicketCommentRowUIView : UIView
{
public TicketCommentRowUIView(IntPtr handle) : base(handle)
{
}
public static TicketCommentRowUIView CreateView(TicketCommentModel model)
{
TicketCommentRowUIView v = CreateView();
v.LoadModelInfo(model);
return v;
}
private static TicketCommentRowUIView CreateView()
{
var arr = NSBundle.MainBundle.LoadNib("TicketCommentRowUIView", null, null);
var v = Runtime.GetNSObject<TicketCommentRowUIView>(arr.ValueAt(0));
return v;
}
private void LoadModelInfo(TicketCommentModel model)
{
DateReply.Text = model.CreatedAt.ToShortDateString();
MessageReply.Text = model.Content;
ReplierImage.Image = UIImage.FromBundle("default_image_user");
}
}
}
And I'm adding that custom view to an stack view in TicketDetailViewController dinamically, but I don't know how to resize the custom view according its self size:
using Foundation;
using System;
using UIKit;
using System.Collections.Generic;
using System.Linq;
using CoreGraphics;
namespace Project.iOS
{
public partial class TicketDetailViewController : UIViewController
{
private nfloat TicketItemHeight = 200;
TicketModel _ticketItem;
List<TicketCommentModel> _ticketCommentsList;
TicketDetailPresenter _presenter;
public TicketDetailViewController (IntPtr handle) : base (handle)
{
_presenter = new TicketDetailPresenter(this);
}
public async override void ViewDidLoad()
{
base.ViewDidLoad();
ScrollView.LoadingStart();
await _presenter.LoadTicketComments(_ticketItem.Id);
FillComentsStackView();
ScrollView.LoadingComplete();
}
public void LoadMenuItem(TicketModel ticketItem)
{
_ticketItem = ticketItem;
}
public void FillComentsStackView()
{
foreach (TicketCommentModel item in _ticketCommentsList)
{
TicketCommentRowUIView itemView = TicketCommentRowUIView.CreateView(item);
itemView.HeightAnchor.ConstraintEqualTo(TicketItemHeight).Active = true;
CommentStackView.AddArrangedSubview(itemView);
}
}
}
}
My issue is that I don't know how to add an self size for each custom view, because the height of MessageReply UILabel it is variable... I put a constraint equals to 200 but when the text is too big it looks overlapped. And when it is a short text there is to much of blank space. Is there any way to do this?? In my android project I just set WrapContent layout params and it worked. But I can't find the way to apply that to the iOS project.
It seems you have set the Label's Line 0 to wrap its content.
Then you can set each item's constraint in your xib to make your custom view self size fit. From your screenshot you can set the left, top constraint of your image and top, left constraint of your DateReply, at last the left, top, right , bottom constraint of the MessageReply like:
Adjust the constant to feed your request. Moreover when you add the custom view in the TicketDetailViewController, there's no need to set the HeightAnchor.

set Height Entry rendered xamarin forms ios

I have need to modify and customize the Entry Control in Xamarin, but I have difficulty setting, or rather to find the method for declaring the height of the control of Xamarin ios.
How can I do ? here is my code.
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyEntryRenderer))]
namespace MyApplication.iOS
{
public class MyEntryRenderer : EntryRenderer
{
//CUSTOM entry RENDER IOS
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.BackgroundColor = UIColor.FromRGB(43, 50, 58);
Control.TextColor = UIColor.FromRGB(255, 255, 255);
//Control.Height ???
}
}
}
}
There's a HeightRequest property on the cross-platform Entry class. Why not set it there and let Xamarin's renderer do the work?
If you want to set it directly in your own renderer try
Control.Frame = new CGRect(0, 0, width, height);
You can set this on PCL/shared side.
public MyEntry()
{
this.HeightRequest = 50;
}

How do I make custom iOS controls for Visual Studio storyboard

Is it possible to create and use custom controls in the storyboard designer for Visual Studio? I have created a test-component as such:
[Register("Test")]
[Category("Controls")]
public class Test : UIView
{
public Test()
: base()
{
}
public Test(IntPtr handle)
: base(handle)
{
}
public override void Draw(RectangleF rect)
{
base.Draw(rect);
var context = UIGraphics.GetCurrentContext();
context.SetFillColor(0.2f, 0.2f, 0.2f, 1f);
context.FillRect(new RectangleF(0, 0, 50, 50));
}
}
This works fine in Xamarin Studio on my mac, but I cannot get it to work in Visual Studio. I cannot seem to get it to register the view into the toolbox. Is there any way to make this work? If not, how can the component be added in code?

Image over a background Image in Blackberry

I want to set the position of one image over a background image. The position could be anywhere on the screen.
Can I have a sample code or a link or tutorial for that?
Here's how I do it:
This works in 4.6.0 and later because of BackgroundFactory
// Create the background image and the image field to put on top
Background bg = BackgroundFactory.createBitmapBackground(Bitmap.getBitmapResource(bgImgPath);
Bitmap bmp = Bitmap.getBitmapResource(imgPath);
BitmapField imgField = new BitmapField(bmp);
// Create the field manager
VerticalFieldManager manager = new VerticalFieldManager()
{
// Overide the sublayout of the field manager to set the position of
// the image directly
protected void sublayout(int width, int height)
{
setPositionChild(imgField, positionX, positionY)
setExtent(width, height)
}
};
// Set the background of the field manager
manager.setBackground(bg);
// add the bitmap field to the field manager
manager.add(imgField);
// add the field manager to the screen
add(manager);
For multiple images you can make a layout manager class and use that position all your images where you want them using similar techniques. There's a tutorial for making and using a layout manager, I'll try and dig it up and post it back here.
If your using 4.5.0 or earlier, I use a layout manager and just add the background image like any other image but add it first so it draws on the bottom.
Like I said I'll try and find that tutorial for the Layout Manager.
You can create a class that extends Manager class
Here you can specify the background image as well as you can position the other image at a position you want
class Test extends MainScreen
{
Test()
{
super();
Bitmap bmp = Bitmap.getBitmapResource("image1.png");
BitmapField bmpf = new BitmapField(bmp);
Mymanager obj = new Mymanager();
obj.add(bmpf);
}
}
class Mymanager extends Manager
{
final Bitmap background = Bitmap.getBitmapResource("back.png");
protected void paint(Graphics g)
{
g.drawrect(0,0,background.getWidth,background.getheight,background,0,0);
}
protected void sublayout(int width, int height)
{
Field field = getfield(0);
layoutchild(field,100,100);
setPositionchild(field,20,10);
setExtent(Display.getWidth,Display.getHeight);
}
}

Resources