How can I overlap bottom navigation with content in xamarin shell tabbar - c#

[assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
namespace App4.Droid
{
public class CustomShellRenderer : ShellRenderer
{
public CustomShellRenderer(Context context) : base(context)
{
}
protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
return new CustomShellBottomNavViewAppearanceTracker();
}
}
public class CustomShellBottomNavViewAppearanceTracker : IShellBottomNavViewAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(BottomNavigationView bottomView)
{
}
public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
(bottomView.Parent as LinearLayout)?.SetBackgroundColor(Color.Transparent.ToAndroid());
bottomView.SetBackgroundColor(Color.Transparent.ToAndroid());
bottomView.LabelVisibilityMode = LabelVisibilityMode.LabelVisibilityUnlabeled;
}
}
}
shell customrenderer in android
I want to overlap the content part and bottom navigation part
I know how to implement purely XAML-only without shell and CustomRender, but I don't want to. Because my project is highly dependent on Shell
ex)
https://github.com/naweed/MauiPlanets
above app is overlap bottom navigation and contentpage
in my case remove tabbar background and remain icons
Simply put, I would like to lower the height of the content page overlapping with the bottom navigation.

Full screen should be able to meet your need, if I understand correctly.
Add this to your MainActivity.cs:
protected override void OnCreate(Bundle savedInstanceState)
{
...
IWindowInsetsController wicController = Window.InsetsController;
Window.SetDecorFitsSystemWindows(false);
Window.SetFlags(WindowManagerFlags.Fullscreen, WindowManagerFlags.Fullscreen);
if (wicController != null)
{
wicController.Hide(WindowInsets.Type.NavigationBars());
}
}

Related

Scroll to Top of Editor Control

I would like to scroll to the first character of the editor control. Currently when new data is imported into the control, the control scrolls to the bottom which isn't the behavior I want. I don't see a clear way to accomplish this.
This needs to be set at load only as the user needs the ability to type without the cursor jumping to the begging during typing.
The following works for me which I've modified from the answer below. This is set in the Custom Rendered for Android:
protected override void OnVisibilityChanged(global::Android.Views.View changedView, [GeneratedEnum] ViewStates visibility)
{
base.OnVisibilityChanged(changedView, visibility);
Control.SetSelection(0);
}
You can custom a CustomEditorRenderer in native solution to achieve that .
Android :
[assembly: ExportRenderer(typeof(Editor), typeof(CustomEditorRenderer))]
namespace AppEntryTest.Droid
{
class CustomEditorRenderer : EditorRenderer
{
public CustomEditorRenderer(Context context) : base(context)
{
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
//set position from 0
Control.SetSelection(0);
}
}
The effect :
iOS :
[assembly: ExportRenderer(typeof(Editor), typeof(CustomEditorRenderer))]
namespace AppEntryTest.iOS
{
class CustomEditorRenderer : EditorRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
Control.BecomeFirstResponder();
NSRange range;
range.Location = 0;
range.Length = 0;
Control.SelectedRange = range;
}
}
The effect :
=============================Update=============================
First , create renderer class in each platform :
Uesd in Xaml as follow :
<Editor Text="{Binding EditorValue}" />
In addition , also can create a custom Editor in Forms :
public class MyEditor : Editor
{
}
Used in Xaml : <local:MyEditor Text="{Binding EditorValue}" />
In rederer class , assembly also need to modify to use the custom Editor .
[assembly: ExportRenderer(typeof(MyEditor), typeof(CustomEditorRenderer))]

Xamarin FOrms iOS: ImageRenderer CreateNativeControl error

I am trying to implement a custom ImageRenderer in iOS subclassing the native UIImageView, but I am having some problems with CreateNativeControl.
In the older Xamarin.Forms version (like 4.2) the custom native class that I initialized with protected override UIImageView CreateNativeControl() { return new NativeImage(); } looks like it never get called (the message I log in the constructor is not shown). The Custom Renderer is correctly initialized (the right message is logged).
In the latest stable version (like 4.4) in overriding of CreateNativeControl the return type it is said that has to be a FormsUIImageView, never heard of it, anyway I also tried to subclass that but same problem as before, it seems it never get called as the constructor message is not logged. The Custom Renderer is correctly initialized (the right message is logged).
Here the code I used:
public class IOSImageView : ImageRenderer
{
public IOSImageView()
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if(Control == null)
{
return;
}
Console.WriteLine("PIPPO created from Custom Renderer"); //this message is correctly logged
}
protected override UIImageView CreateNativeControl() //FormsUIImageView in XF 4.4
{
return new NativeImage();
}
}
public class NativeImage : UIImageView //FormsUIImageView in XF 4.4
{
public NativeImage() : base()
{
Console.WriteLine("PIPPO created from native IOS"); //this message is NOT logged
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
Console.WriteLine("PIPPO touched"); //this (of course because no NativeImage is shown and there is no image to touch) is NOT logged
}
}
FormsUIImageView is new after XF 4.4 which you can check Xamarin.Forms release notes
In your case , you seems want to set the Image Renderer as your custom ImageView, right?
You should invoked SetNativeControl()
protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
SetNativeControl(new NativeImage());
}
}
public class NativeImage : FormsUIImageView
{
public NativeImage() : base()
{
this.UserInteractionEnabled = true;
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
Console.WriteLine("PIPPO touched"); //this (of course because no NativeImage is shown and there is no image to touch) is NOT logged
}
}

UserControl with header and content - Allow dropping controls in content panel and Prevent dropping controls in header at design time

I wrote User Control (yay!). But I want it to behave as a container. But wait! I know about
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design",
typeof(IDesigner))]
Trick.
The problem is - I don't want all of my control to behave like container, but only one part. One - de facto - panel ;)
To give wider context: I wrote a control that has Grid, some common buttons, labels and functionalities. But it also has a part where the user is supposed to drop his custom buttons/controls whatever. Only in this particular part of the control, nowhere else.
Anyone had any idea?
You should do the following :
For your user control, you need to create a new designer which enables the inner panel on design-time by calling EnableDesignMode method.
For the inner panel, you need to create a designer which disables moving, resizing and removes some properties from designer.
You should register the designers.
Example
You can read a blog post about this topic here and clone or download a working example:
r-aghaei/ChildContainerControlDesignerSample
Download Zip
Code
Here is the code for different elements of the solution.
Your user control
[Designer(typeof(MyUserControlDesigner))]
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
TypeDescriptor.AddAttributes(this.panel1,
new DesignerAttribute(typeof(MyPanelDesigner)));
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel ContentsPanel
{
get { return panel1; }
}
}
Designer for the inner panel
public class MyPanelDesigner : ParentControlDesigner
{
public override SelectionRules SelectionRules
{
get
{
SelectionRules selectionRules = base.SelectionRules;
selectionRules &= ~SelectionRules.AllSizeable;
return selectionRules;
}
}
protected override void PostFilterAttributes(IDictionary attributes)
{
base.PostFilterAttributes(attributes);
attributes[typeof(DockingAttribute)] =
new DockingAttribute(DockingBehavior.Never);
}
protected override void PostFilterProperties(IDictionary properties)
{
base.PostFilterProperties(properties);
var propertiesToRemove = new string[] {
"Dock", "Anchor", "Size", "Location", "Width", "Height",
"MinimumSize", "MaximumSize", "AutoSize", "AutoSizeMode",
"Visible", "Enabled",
};
foreach (var item in propertiesToRemove)
{
if (properties.Contains(item))
properties[item] = TypeDescriptor.CreateProperty(this.Component.GetType(),
(PropertyDescriptor)properties[item],
new BrowsableAttribute(false));
}
}
}
Designer for your user control
public class MyUserControlDesigner : ParentControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
var contentsPanel = ((MyUserControl)this.Control).ContentsPanel;
this.EnableDesignMode(contentsPanel, "ContentsPanel");
}
public override bool CanParent(Control control)
{
return false;
}
protected override void OnDragOver(DragEventArgs de)
{
de.Effect = DragDropEffects.None;
}
protected override IComponent[] CreateToolCore(ToolboxItem tool, int x,
int y, int width, int height, bool hasLocation, bool hasSize)
{
return null;
}
}

UserControl extending ScrollableControl - disable container functinality

I'm building custom control by extending ScrollableControl.
Problem is that my custom control acts as container - I can drag controls into it:
My question is how can I disable container functionality in class that extends ScrollableControl
Below are two test controls, one extends Control, second ScrollableControl
public class ControlBasedControl : Control
{
protected override Size DefaultSize
{
get { return new Size(100, 100); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillRectangle(Brushes.LightCoral, ClientRectangle);
}
}
public class ScrollableControlBasedControl : ScrollableControl
{
public ScrollableControlBasedControl()
{
AutoScrollMinSize = new Size(200, 200);
}
protected override Size DefaultSize
{
get { return new Size(100, 100); }
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillRectangle(Brushes.LawnGreen, ClientRectangle);
}
}
You get "acts-like-a-container" behavior at design time from the [Designer] attribute. Copy-pasting from the Reference Source:
[
ComVisible(true),
ClassInterface(ClassInterfaceType.AutoDispatch),
Designer("System.Windows.Forms.Design.ScrollableControlDesigner, " + AssemblyRef.SystemDesign)
]
public class ScrollableControl : Control, IArrangedElement {
// etc...
}
It is ScrollableControlDesigner that gets the job done. Doesn't do much by itself, but derived from ParentControlDesigner, the designer that permits a control to act as a parent for child controls and gives it container-like behavior at design time.
Fix is easy, you just have to use your own [Designer] attribute to select another designer. Add a reference to System.Design and make it look like this:
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms.Design; // Add reference to System.Design
[Designer(typeof(ControlDesigner))]
public class ScrollableControlBasedControl : ScrollableControl {
// etc...
}
There is probably more than one way to accomplish this, but here is what I would do...
First create a read-only version of ControlCollection
public class ReadOnlyControlCollection : Control.ControlCollection
{
public ReadOnlyControlCollection(Control owner)
: base(owner)
{
}
public override bool IsReadOnly
{
get { return true; }
}
public override void Add(Control control)
{
throw new ArgumentException("control");
}
}
Then make your ScrollableControlBasedControl create an instance of ReadOnlyControlCollection in stead of the default ControlCollection
public class ScrollableControlBasedControl : ScrollableControl
{
protected override Control.ControlCollection CreateControlsInstance()
{
return new ReadOnlyControlCollection(this);
}
// The rest of your class goes here...
}
I use Visual Studio 2010 and when I drop a control on an ScrollableControlBasedControl the control is magically moved back to where it came from, as if the action was cancelled.

Prevent adding controls from toolbox to a UserControl at Design Time [duplicate]

I wrote User Control (yay!). But I want it to behave as a container. But wait! I know about
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design",
typeof(IDesigner))]
Trick.
The problem is - I don't want all of my control to behave like container, but only one part. One - de facto - panel ;)
To give wider context: I wrote a control that has Grid, some common buttons, labels and functionalities. But it also has a part where the user is supposed to drop his custom buttons/controls whatever. Only in this particular part of the control, nowhere else.
Anyone had any idea?
You should do the following :
For your user control, you need to create a new designer which enables the inner panel on design-time by calling EnableDesignMode method.
For the inner panel, you need to create a designer which disables moving, resizing and removes some properties from designer.
You should register the designers.
Example
You can read a blog post about this topic here and clone or download a working example:
r-aghaei/ChildContainerControlDesignerSample
Download Zip
Code
Here is the code for different elements of the solution.
Your user control
[Designer(typeof(MyUserControlDesigner))]
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
TypeDescriptor.AddAttributes(this.panel1,
new DesignerAttribute(typeof(MyPanelDesigner)));
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel ContentsPanel
{
get { return panel1; }
}
}
Designer for the inner panel
public class MyPanelDesigner : ParentControlDesigner
{
public override SelectionRules SelectionRules
{
get
{
SelectionRules selectionRules = base.SelectionRules;
selectionRules &= ~SelectionRules.AllSizeable;
return selectionRules;
}
}
protected override void PostFilterAttributes(IDictionary attributes)
{
base.PostFilterAttributes(attributes);
attributes[typeof(DockingAttribute)] =
new DockingAttribute(DockingBehavior.Never);
}
protected override void PostFilterProperties(IDictionary properties)
{
base.PostFilterProperties(properties);
var propertiesToRemove = new string[] {
"Dock", "Anchor", "Size", "Location", "Width", "Height",
"MinimumSize", "MaximumSize", "AutoSize", "AutoSizeMode",
"Visible", "Enabled",
};
foreach (var item in propertiesToRemove)
{
if (properties.Contains(item))
properties[item] = TypeDescriptor.CreateProperty(this.Component.GetType(),
(PropertyDescriptor)properties[item],
new BrowsableAttribute(false));
}
}
}
Designer for your user control
public class MyUserControlDesigner : ParentControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
var contentsPanel = ((MyUserControl)this.Control).ContentsPanel;
this.EnableDesignMode(contentsPanel, "ContentsPanel");
}
public override bool CanParent(Control control)
{
return false;
}
protected override void OnDragOver(DragEventArgs de)
{
de.Effect = DragDropEffects.None;
}
protected override IComponent[] CreateToolCore(ToolboxItem tool, int x,
int y, int width, int height, bool hasLocation, bool hasSize)
{
return null;
}
}

Categories