Making Facebook like comment input functionality

Hi,

I want to make a comment input area in my App which has functionality which is similar to that found on Facebook. A short description of the functionality is a comment input area which starts of as one line and which extends to more lines as you write. As you keep on writhing to you get to a fixed height and the input area then changes to a scroll view.

I have been looking at a combination of TextView and ScrollView to achieve this functionality, but I don’t manage to give the focus back to the ScrollView if the user is typing to allow for scrolling.

Any suggestions on how to create this functionality?

Here is my current implementation which does not work:

<App>
	<JavaScript>
		var Observable = require("FuseJS/Observable");
		var showScrollIndicator = Observable(false);
		var commentHeight = Observable(false);

		function textInputHeight (arg) {
			 if (arg.height > 130) {
		            	commentHeight.value = true;
					} else {
		            	commentHeight.value = false;
				}
			}

		function valueChanged () {
			commentScrollView.gotoRelative(0, 1);
			showScrollIndicator.value = false;
			}	

		function scrollIndicatorActive () {
				if (commentHeight.value == true) {
						showScrollIndicator.value = true;
					} else {
			            	showScrollIndicator.value = false;	            	
					}
			}								

		module.exports = {
			valueChanged: valueChanged,
			scrollIndicatorActive: scrollIndicatorActive,
			showScrollIndicator: showScrollIndicator,
			textInputHeight: textInputHeight,
			commentHeight: commentHeight
		};
	</JavaScript>

	<DockPanel ux:Name="makeComment" MaxHeight="150">
		<Panel Dock="Left" Alignment="Bottom">
	        <Image Margin="10,5,10,5" Width="30" Height="30" File="../assets/images/user-avatar-blue.png"  Dock="Left" />
	    </Panel>
	    <Panel Dock="Left" Width="65%" MaxHeight="150" Padding="0,10,0,10" Alignment="Left">
	    	<WhileTrue Value="{showScrollIndicator}" >
	        	<Rectangle Height="50%" Width="2" Margin="2,0,2,0"   Alignment="TopRight" ux:Name="scrollIndicator" Opacity="0">
	                <SolidColor Color="#ddd" />
	            </Rectangle>
	            <GiveFocus Target="commentScrollView" />
	            <BringToFront Target="commentScrollView" />
	        </WhileTrue>
	     	<ScrollView ux:Name="commentScrollView" SnapMinTransform="true" SnapMaxTransform="true" KeepFocusInView="false" LayoutMode="PreserveScrollPosition" Focus.IsFocusable="true">
			    <WhileInteracting>
					<Change scrollIndicator.Opacity="1" />
					<GiveFocus Target="commentScrollView" />
					<BringToFront Target="commentScrollView" />
				</WhileInteracting>
	     		<ScrollingAnimation>
	                <Move Y="0.5" RelativeNode="commentScrollView" RelativeTo="Size" Target="scrollIndicator" />
	            </ScrollingAnimation>
	     		<DockPanel HitTestMode="LocalVisualAndChildren">
					<TextView Value="{Comment}" ux:Name="postCommen" ValueChanged="{valueChanged}" TextWrapping="Wrap" FontSize="16" Moved="{scrollIndicatorActive}" Placed="{textInputHeight}" >
	                    <WhileString Test="IsEmpty">
	                        <Text TextWrapping="Wrap" TextColor="#878c93" FontSize="16" Alignment="Left" >Write a comment</Text>
	                        <Set Post.TextColor="#878c93" />
	                        <Set scrollIndicator.Opacity="0" />
	                    </WhileString> 
	                    <WhileString Test="IsNotEmpty">
	                        <Set Post.TextColor="red" />
	                    </WhileString>
	                    <WhileFocusWithin>
							<Change scrollIndicator.Opacity="0" />
						</WhileFocusWithin>
	                </TextView>
	            </DockPanel>
	        </ScrollView>
	    </Panel>
	    <Panel Dock="Right" Alignment="Bottom">
	         <Text ux:Name="Post" Margin="10,10,10,0" Value="Post" Height="30" FontSize="16" TextColor="#878c93" />
	    </Panel>
	</DockPanel> 
</App>        

A TextView is implicitly scrollable as the content of it exceeds the visible dimensions. Combining that with a ScrollView and juggling focus between elements sounds like a recipe for disaster.

Here’s a simple snippet that does something like what you’re after (make sure you test on a physical device):

<App>
    <DockPanel>
        <StatusBarBackground Dock="Top" />
        <BottomBarBackground Dock="Bottom" IncludesKeyboard="true" />
        <DockPanel Dock="Bottom">
            <Panel Dock="Left" Width="48" Height="48" Color="#f00" Alignment="Bottom" />
            <Panel Dock="Right" Width="48" Height="48" Color="#00f" Alignment="Bottom">
                <Text Value="Post" Alignment="VerticalCenter" TextAlignment="Center" TextColor="#fff" />
            </Panel>
            <TextView TextWrapping="Wrap" Margin="8,0" MaxHeight="96" Background="#0002" />
        </DockPanel>
        <Panel />
    </DockPanel>
</App>   

However, if you explicitly need a scrolling indicator, then this gets much more involved. Currently, there are no properties available on TextView that would allow you to know the relative ScrollPosition or something along those lines, which basically renders the challenge impossible.

A way forward could be to use a hidden TextInput, and coding the visual representation using other controls, including a Text data-bound to the Observable content, a ScrollView and others. The Code input example should get you started in the right direction.

Hope this helps!