Permalink
Switch branches/tags
tag-test3 tag-test2 tag-test1 rui-3.0.0 release-3.4.0-rc1.3 release-3.4.0-rc1.2 release-3.4.0-rc1.1 release-3.4.0-rc1 release-3.3.0-sr1.2 release-3.3.0-sr1.1 release-3.3.0-sr1 release-3.3.0-rc0 release-3.2.0 release-3.2.0-sr1 release-3.1.0-sr3 release-3.1.0-sr2 release-3.1.0-sr1.1 release-3.1.0-sr1 release-3.1.0-rc1 release-3.0.0-sr4.1 release-3.0.0-sr4 release-3.0.0-sr3 release-3.0.0-sr2 release-3.0.0-sr1 release-3.0.0-rc2 release-3.0.0-rc1 release-2.5.1 release-2.5.1-sr4 release-2.5.1-sr3 release-2.5.1-sr2 release-2.5.1-sr1 release-2.5.0 release-2.5.0-sr5 release-2.5.0-sr4 release-2.5.0-sr3 release-2.5.0-sr2 release-2.5.0-sr1 release-2.4.99-rc1 release-2.4.0 release-2.4.0-sr6 release-2.4.0-sr5 release-2.4.0-sr4 release-2.4.0-sr3 release-2.4.0-sr2 release-2.4.0-sr1 release-2.4.0-rc2 release-2.3.5 release-2.3.4 release-2.3.4-sr6 release-2.3.4-sr5 release-2.3.4-sr4 release-2.3.4-sr3 release-2.3.4-sr2 release-2.3.4-sr1 release-2.3.3 release-2.3.3-sr2 release-2.3.3-sr1.1 release-2.3.3-sr1 release-2.3.3-hf1 release-2.3.2 release-2.3.2-hf1 release-2.3.1 release-2.3.0 release-2.3.0-hf1 release-2.2.0 release-2.2.0-hf1 beta-cycle6buildtest beta-9.99.99-rui beta-9.9.999-rui beta-9.9.99-rui beta-9.9.15.5-rui beta-9.9.9.9-rui beta-9.9.9-rui beta-9.9.8-rui beta-3.5.0-pre1.1 beta-3.5.0-pre1 beta-3.4.0-rui beta-3.4.0-pre2.2 beta-3.4.0-pre2.1 beta-3.4.0-pre2 beta-3.4.0-pre1 beta-3.3.0-pre3 beta-3.3.0-pre2 beta-3.3.0-pre1 beta-3.2.0-pre3 beta-3.2.0-pre2 beta-3.2.0-pre1.1 beta-3.2.0-pre1 beta-3.1.0-pre4.1 beta-3.1.0-pre4 beta-3.1.0-pre3 beta-3.1.0-pre2.3 beta-3.1.0-pre2.2 beta-3.1.0-pre2 beta-3.1.0-pre1.2 beta-3.1.0-pre1 beta-3.0.0-rui beta-3.0.0-pre4.4 beta-3.0.0-pre4.3 beta-3.0.0-pre4.2
Nothing to show
Find file Copy path
332 lines (269 sloc) 7.87 KB
using System;
using System.ComponentModel;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Views;
using AView = Android.Views.View;
using Xamarin.Forms.Platform.Android.FastRenderers;
namespace Xamarin.Forms.Platform.Android
{
public interface IViewRenderer
{
void MeasureExactly();
}
public abstract class ViewRenderer : ViewRenderer<View, AView>
{
protected ViewRenderer(Context context) : base(context)
{
}
[Obsolete("This constructor is obsolete as of version 2.5. Please use ViewRenderer(Context) instead.")]
protected ViewRenderer()
{
}
}
public abstract class ViewRenderer<TView, TNativeView> : VisualElementRenderer<TView>, IViewRenderer, ITabStop, AView.IOnFocusChangeListener where TView : View where TNativeView : AView
{
protected ViewRenderer(Context context) : base(context)
{
}
[Obsolete("This constructor is obsolete as of version 2.5. Please use ViewRenderer(Context) instead.")]
protected ViewRenderer()
{
}
protected virtual TNativeView CreateNativeControl()
{
return default(TNativeView);
}
ViewGroup _container;
string _defaultContentDescription;
bool? _defaultFocusable;
string _defaultHint;
bool _disposed;
EventHandler<VisualElement.FocusRequestArgs> _focusChangeHandler;
SoftInput _startingInputMode;
internal bool HandleKeyboardOnFocus;
public TNativeView Control { get; private set; }
AView ITabStop.TabStop => Control;
void IViewRenderer.MeasureExactly()
{
MeasureExactly(Control, Element, Context);
}
// This is static so it's also available for use by the fast renderers
internal static void MeasureExactly(AView control, VisualElement element, Context context)
{
if (control == null || element == null)
{
return;
}
var width = element.Width;
var height = element.Height;
if (width <= 0 || height <= 0)
{
return;
}
var realWidth = (int)context.ToPixels(width);
var realHeight = (int)context.ToPixels(height);
var widthMeasureSpec = MeasureSpecFactory.MakeMeasureSpec(realWidth, MeasureSpecMode.Exactly);
var heightMeasureSpec = MeasureSpecFactory.MakeMeasureSpec(realHeight, MeasureSpecMode.Exactly);
control.Measure(widthMeasureSpec, heightMeasureSpec);
}
void AView.IOnFocusChangeListener.OnFocusChange(AView v, bool hasFocus)
{
if (Element is Entry || Element is SearchBar || Element is Editor)
{
var isInViewCell = false;
Element parent = Element.RealParent;
while (!(parent is Page) && parent != null)
{
if (parent is Cell)
{
isInViewCell = true;
break;
}
parent = parent.RealParent;
}
if (isInViewCell)
{
Window window = ((Activity)Context).Window;
if (hasFocus)
{
_startingInputMode = window.Attributes.SoftInputMode;
window.SetSoftInputMode(SoftInput.AdjustPan);
}
else
window.SetSoftInputMode(_startingInputMode);
}
}
OnNativeFocusChanged(hasFocus);
((IElementController)Element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, hasFocus);
}
public override SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint)
{
if (Control == null)
return (base.GetDesiredSize(widthConstraint, heightConstraint));
AView view = _container == this ? (AView)Control : _container;
view.Measure(widthConstraint, heightConstraint);
return new SizeRequest(new Size(Control.MeasuredWidth, Control.MeasuredHeight), MinimumSize());
}
protected override void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
if (Control != null && ManageNativeControlLifetime)
{
Control.OnFocusChangeListener = null;
RemoveView(Control);
Control.Dispose();
Control = null;
}
if (_container != null && _container != this)
{
_container.RemoveFromParent();
_container.Dispose();
_container = null;
}
if (Element != null && _focusChangeHandler != null)
{
Element.FocusChangeRequested -= _focusChangeHandler;
_focusChangeHandler = null;
}
_disposed = true;
}
base.Dispose(disposing);
}
protected override void OnElementChanged(ElementChangedEventArgs<TView> e)
{
base.OnElementChanged(e);
if (_focusChangeHandler == null)
_focusChangeHandler = OnFocusChangeRequested;
if (e.OldElement != null)
e.OldElement.FocusChangeRequested -= _focusChangeHandler;
if (e.NewElement != null)
e.NewElement.FocusChangeRequested += _focusChangeHandler;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
UpdateIsEnabled();
else if (e.PropertyName == AutomationProperties.LabeledByProperty.PropertyName)
SetLabeledBy();
else if (e.PropertyName == VisualElement.FlowDirectionProperty.PropertyName)
UpdateFlowDirection();
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (Control == null)
return;
AView view = _container == this ? (AView)Control : _container;
view.Measure(MeasureSpecFactory.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly), MeasureSpecFactory.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly));
view.Layout(0, 0, r - l, b - t);
}
protected override void OnRegisterEffect(PlatformEffect effect)
{
base.OnRegisterEffect(effect);
effect.SetControl(Control);
}
protected override void SetAutomationId(string id)
{
if (Control == null)
{
base.SetAutomationId(id);
return;
}
ContentDescription = id + "_Container";
AutomationPropertiesProvider.SetAutomationId(Control, Element, id);
}
protected override void SetContentDescription()
{
if (Control == null)
{
base.SetContentDescription();
return;
}
AutomationPropertiesProvider.SetContentDescription(
Control, Element, ref _defaultContentDescription, ref _defaultHint);
}
protected override void SetFocusable()
{
if (Control == null)
{
base.SetFocusable();
return;
}
AutomationPropertiesProvider.SetFocusable(Control, Element, ref _defaultFocusable);
}
protected void SetNativeControl(TNativeView control)
{
SetNativeControl(control, this);
}
internal virtual void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
{
if (Control == null)
return;
e.Result = true;
if (e.Focus)
{
// use post being BeginInvokeOnMainThread will not delay on android
Looper looper = Context.MainLooper;
var handler = new Handler(looper);
handler.Post(() =>
{
Control?.RequestFocus();
});
}
else
{
Control.ClearFocus();
}
//handles keyboard on focus for Editor, Entry and SearchBar
if (HandleKeyboardOnFocus)
{
if (e.Focus)
Control.ShowKeyboard();
else
Control.HideKeyboard();
}
}
internal virtual void OnNativeFocusChanged(bool hasFocus)
{
}
internal override void SendVisualElementInitialized(VisualElement element, AView nativeView)
{
base.SendVisualElementInitialized(element, Control);
}
internal void SetNativeControl(TNativeView control, ViewGroup container)
{
if (Control != null)
{
Control.OnFocusChangeListener = null;
RemoveView(Control);
}
_container = container;
Control = control;
if (Control.Id == NoId)
{
Control.Id = Platform.GenerateViewId();
}
AView toAdd = container == this ? control : (AView)container;
AddView(toAdd, LayoutParams.MatchParent);
Control.OnFocusChangeListener = this;
UpdateIsEnabled();
UpdateFlowDirection();
SetLabeledBy();
}
void SetLabeledBy()
=> AutomationPropertiesProvider.SetLabeledBy(Control, Element);
void UpdateIsEnabled()
{
if (Control != null)
Control.Enabled = Element.IsEnabled;
}
void UpdateFlowDirection()
{
Control.UpdateFlowDirection(Element);
}
}
}