Skip to content

Commit

Permalink
fix(TextInput): Support auto-grow for TextInput (#1532)
Browse files Browse the repository at this point in the history
The best way to support variable size TextInput is with the auto-grow property. This PR updates the JS for the TextInput component and adds the necessary changes to support auto-grow on UWP.

Towards #272
  • Loading branch information
rozele authored Nov 17, 2017
1 parent 7251e03 commit a83eb74
Show file tree
Hide file tree
Showing 12 changed files with 744 additions and 301 deletions.
797 changes: 546 additions & 251 deletions Libraries/Components/TextInput/TextInput.windows.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;
using ReactNative.Reflection;
using ReactNative.UIManager;
using ReactNative.UIManager.Annotations;
Expand Down Expand Up @@ -399,10 +399,9 @@ public override void OnDropViewInstance(ThemedReactContext reactContext, Passwor
/// <param name="dimensions">The output buffer.</param>
public override void SetDimensions(PasswordBox view, Dimensions dimensions)
{
Canvas.SetLeft(view, dimensions.X);
Canvas.SetTop(view, dimensions.Y);
view.Width = dimensions.Width;
view.Height = dimensions.Height;
base.SetDimensions(view, dimensions);
view.MinWidth = dimensions.Width;
view.MinHeight = dimensions.Height;
}

private void OnPasswordChanged(object sender, RoutedEventArgs e)
Expand All @@ -415,8 +414,6 @@ private void OnPasswordChanged(object sender, RoutedEventArgs e)
new ReactTextChangedEvent(
textBox.GetTag(),
textBox.Password,
textBox.ActualWidth,
textBox.ActualHeight,
0));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,9 @@ public override void OnDropViewInstance(ThemedReactContext reactContext, ReactTe

public override void SetDimensions(ReactTextBox view, Dimensions dimensions)
{
Canvas.SetLeft(view, dimensions.X);
Canvas.SetTop(view, dimensions.Y);
view.Width = dimensions.Width;
view.Height = dimensions.Height;
base.SetDimensions(view, dimensions);
view.MinWidth = dimensions.Width;
view.MinHeight = dimensions.Height;
}

/// <summary>
Expand Down Expand Up @@ -518,8 +517,6 @@ private void OnTextChanged(object sender, TextChangedEventArgs e)
new ReactTextChangedEvent(
textBox.GetTag(),
textBox.Text,
textBox.ActualWidth,
textBox.ActualHeight,
textBox.CurrentEventCount));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Views\Slider\ReactSliderChangeEvent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\Slider\ReactSliderCompleteEvent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\Slider\ReactSliderShadowNode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\TextInput\ReactTextInputContentSizeChangedEvent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\Text\FontStyleHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\Text\ReactInlineShadowNode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Views\Text\ReactInlineShadowNodeVisitor.cs" />
Expand Down
4 changes: 2 additions & 2 deletions ReactWindows/ReactNative.Shared/UIManager/LayoutShadowNode.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Facebook.Yoga;
using Facebook.Yoga;
using Newtonsoft.Json.Linq;
using ReactNative.Reflection;
using ReactNative.UIManager.Annotations;
Expand Down Expand Up @@ -111,7 +111,7 @@ public void SetMinHeight(JValue minHeight)
/// </summary>
/// <param name="maxHeight">The maximum height.</param>
[ReactProp(ViewProps.MaxHeight, DefaultSingle = YogaConstants.Undefined)]
public void SetMaxHeight(JValue maxHeight)
public virtual void SetMaxHeight(JValue maxHeight)
{
if (IsVirtual)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,13 @@ private static Dictionary<string, object> GetDirectEventTypeConstants()
{ "registrationName", "onLoadingError" },
}
},
{
"topContentSizeChange",
new Map
{
{ "registrationName", "onContentSizeChange" },
}
},
{
"topLayout",
new Map
Expand Down
47 changes: 34 additions & 13 deletions ReactWindows/ReactNative.Shared/Views/TextInput/ReactTextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class ReactTextBox : TextBox
{
private int _eventCount;
private bool _selectionChangedSubscribed;
private bool _sizeChangedSubscribed;

public int CurrentEventCount
{
Expand Down Expand Up @@ -48,16 +49,45 @@ public bool OnSelectionChange
_selectionChangedSubscribed = value;
if (_selectionChangedSubscribed)
{
this.SelectionChanged += OnSelectionChanged;
SelectionChanged += OnSelectionChanged;
}
else
{
this.SelectionChanged -= OnSelectionChanged;
SelectionChanged -= OnSelectionChanged;
}
}
}
}

public bool OnContentSizeChange
{
get
{
return _sizeChangedSubscribed;
}
set
{
if (value != _sizeChangedSubscribed)
{
_sizeChangedSubscribed = value;
if (_sizeChangedSubscribed)
{
SizeChanged += OnSizeChanged;
}
else
{
SizeChanged -= OnSizeChanged;
}
}
}
}

public bool AutoGrow
{
get;
set;
}

public int IncrementEventCount()
{
return Interlocked.Increment(ref _eventCount);
Expand All @@ -66,7 +96,6 @@ public int IncrementEventCount()
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
SizeChanged += OnSizeChanged;

if (ClearTextOnFocus)
{
Expand All @@ -80,24 +109,16 @@ protected override void OnGotFocus(RoutedEventArgs e)
}
}

protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
SizeChanged -= OnSizeChanged;
}

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
this.GetReactContext()
.GetNativeModule<UIManagerModule>()
.EventDispatcher
.DispatchEvent(
new ReactTextChangedEvent(
new ReactTextInputContentSizeChangedEvent(
this.GetTag(),
Text,
e.NewSize.Width,
e.NewSize.Height,
IncrementEventCount()));
e.NewSize.Height));
}

private void OnSelectionChanged(object sender, RoutedEventArgs e)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;
using ReactNative.UIManager.Events;
using System;

Expand All @@ -11,24 +11,18 @@ namespace ReactNative.Views.TextInput
class ReactTextChangedEvent : Event
{
private readonly string _text;
private readonly double _contextWidth;
private readonly double _contentHeight;
private readonly int _eventCount;

/// <summary>
/// Instantiates a <see cref="ReactTextChangedEvent"/>.
/// </summary>
/// <param name="viewTag">The view tag.</param>
/// <param name="text">The text.</param>
/// <param name="contentWidth">The content width.</param>
/// <param name="contentHeight">The content height.</param>
/// <param name="eventCount">The event count.</param>
public ReactTextChangedEvent(int viewTag, string text, double contentWidth, double contentHeight, int eventCount)
public ReactTextChangedEvent(int viewTag, string text, int eventCount)
: base(viewTag)
{
_text = text;
_contextWidth = contentWidth;
_contentHeight = contentHeight;
_eventCount = eventCount;
}

Expand Down Expand Up @@ -63,16 +57,9 @@ public override bool CanCoalesce
/// <param name="rctEventEmitter">The event emitter.</param>
public override void Dispatch(RCTEventEmitter rctEventEmitter)
{
var contentSize = new JObject
{
{ "width", _contextWidth },
{ "height", _contentHeight },
};

var eventData = new JObject
{
{ "text", _text },
{ "contentSize", contentSize },
{ "eventCount", _eventCount },
{ "target", ViewTag },
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Newtonsoft.Json.Linq;
using ReactNative.UIManager.Events;

namespace ReactNative.Views.TextInput
{
class ReactTextInputContentSizeChangedEvent : Event
{
private readonly double _width;
private readonly double _height;

public ReactTextInputContentSizeChangedEvent(
int viewTag,
double width,
double height)
: base(viewTag)
{
_height = height;
_width = width;
}

public override string EventName
{
get
{
return "topContentSizeChange";
}
}

public override void Dispatch(RCTEventEmitter eventEmitter)
{
eventEmitter.receiveEvent(ViewTag, EventName, new JObject
{
{ "target", ViewTag },
{
"contentSize",
new JObject
{
{ "width", _width },
{ "height", _height },
}
},
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ public class ReactTextInputShadowNode : LayoutShadowNode
private float[] _computedPadding;

private bool _multiline;
private bool _autoGrow;
private int _letterSpacing;
private int _numberOfLines;

private double _fontSize = Unset;
private double _lineHeight;
private double? _maxHeight;

private FontStyle? _fontStyle;
private FontWeight? _fontWeight;
Expand Down Expand Up @@ -170,7 +172,7 @@ public void SetLetterSpacing(int letterSpacing)
/// </summary>
/// <param name="lineHeight">The line height.</param>
[ReactProp(ViewProps.LineHeight)]
public virtual void SetLineHeight(double lineHeight)
public void SetLineHeight(double lineHeight)
{
if (_lineHeight != lineHeight)
{
Expand All @@ -179,12 +181,27 @@ public virtual void SetLineHeight(double lineHeight)
}
}

/// <summary>
/// Sets the max height.
/// </summary>
/// <param name="maxHeight">The max height.</param>
[ReactProp(ViewProps.MaxHeight)]
public override void SetMaxHeight(JValue maxHeight)
{
var maxHeightValue = maxHeight.Value<double?>();
if (_maxHeight != maxHeightValue)
{
_maxHeight = maxHeightValue;
MarkUpdated();
}
}

/// <summary>
/// Sets the maximum number of lines.
/// </summary>
/// <param name="numberOfLines">Max number of lines.</param>
[ReactProp(ViewProps.NumberOfLines)]
public virtual void SetNumberOfLines(int numberOfLines)
public void SetNumberOfLines(int numberOfLines)
{
if (_numberOfLines != numberOfLines)
{
Expand All @@ -207,6 +224,23 @@ public void SetMultiline(bool multiline)
}
}

/// <summary>
/// Sets whether to enable auto-grow on the text input.
/// </summary>
/// <param name="autoGrow">The auto-grow flag.</param>
[ReactProp("autoGrow")]
public void SetAutoGrow(bool autoGrow)
{
if (_autoGrow != autoGrow)
{
_autoGrow = autoGrow;
if (!_autoGrow)
{
MarkUpdated();
}
}
}

/// <summary>
/// Sets the text alignment.
/// </summary>
Expand Down Expand Up @@ -342,6 +376,11 @@ private static void ApplyStyles(ReactTextInputShadowNode textNode, TextBlock tex
var fontFamily = new FontFamily(textNode._fontFamily);
textBlock.FontFamily = fontFamily;
}

if (textNode._maxHeight.HasValue)
{
textBlock.MaxHeight = textNode._maxHeight.Value;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,6 @@ private void OnPasswordChanged(object sender, RoutedEventArgs e)
new ReactTextChangedEvent(
textBox.GetTag(),
textBox.Password,
textBox.ActualWidth,
textBox.ActualHeight,
0));
}

Expand Down
Loading

0 comments on commit a83eb74

Please sign in to comment.