public VectorSpeechBubblePage()
        {
            this.Title           = "Vector Speech Bubble";
            this.BackgroundColor = ColorHelper.MyLightBlue.ToFormsColor();

            var bubble = new VectorSpeechBubble {
                Text           = "Hello there. Do you have a minute to talk?",
                ArrowDirection = ArrowDirections.RightBottom,
                BorderColor    = Color.White,
                BorderWidth    = 4d,
                // Padding = new Thickness(8d,8d,8d,8d),	// TODO: Auto calculate padding based on the arrow direction and size.  This padding should be in addition to
                HasShadow         = true,
                HorizontalOptions = LayoutOptions.Start,
                VerticalOptions   = LayoutOptions.Start,
            };

            var arrowDirectionPicker = new Picker {
                HorizontalOptions = LayoutOptions.End,
                WidthRequest      = 150d,
            };

            foreach (var direction in System.Enum.GetNames(typeof(ArrowDirections)))
            {
                arrowDirectionPicker.Items.Add(direction);
            }
            arrowDirectionPicker.SelectedIndex = arrowDirectionPicker.Items.IndexOf(ArrowDirections.RightBottom.ToString());

            arrowDirectionPicker.SelectedIndexChanged += (object sender, System.EventArgs e) => {
                var selectedValue = arrowDirectionPicker.Items[arrowDirectionPicker.SelectedIndex];
                var direction     = (ArrowDirections)System.Enum.Parse(typeof(ArrowDirections), selectedValue);
                bubble.ArrowDirection = direction;
            };

            var shadowSwitch = new Switch()
            {
                HorizontalOptions = LayoutOptions.End, WidthRequest = 150d
            };

            var fillColorPicker = new ColorPicker()
            {
                HorizontalOptions = LayoutOptions.End, WidthRequest = 150d
            };

            fillColorPicker.SelectedColor = Color.Silver;

            var gradientColorPicker = new ColorPicker()
            {
                HorizontalOptions = LayoutOptions.End, WidthRequest = 150d
            };

            gradientColorPicker.SelectedColor = Color.Default;

            var borderColorPicker = new ColorPicker()
            {
                HorizontalOptions = LayoutOptions.End, WidthRequest = 150d
            };

            borderColorPicker.SelectedColor = Color.Purple;

            var borderWidthSlider = new Slider(0d, 100d, 4d)
            {
                HorizontalOptions = LayoutOptions.End, WidthRequest = 150d
            };
            var cornerRadiusSlider = new Slider(0d, 50d, 10d)
            {
                HorizontalOptions = LayoutOptions.End, WidthRequest = 150d
            };

            var widthSlider = new Slider {
                Minimum           = 0d,
                Maximum           = Application.Current.MainPage.Width - 20d,
                Value             = Application.Current.MainPage.Width,
                HorizontalOptions = LayoutOptions.End,
                WidthRequest      = 150d,
            };
            var heightSlider = new Slider {
                Minimum           = 0d,
                Maximum           = 300d,
                Value             = 50d,
                HorizontalOptions = LayoutOptions.End,
                WidthRequest      = 150d,
            };

            var sliderLabelStyle = new Style(typeof(Label))
            {
                Setters =
                {
                    new Setter {
                        Property = Label.FontProperty, Value = Font.SystemFontOfSize(NamedSize.Micro)
                    },
                    new Setter {
                        Property = Label.YAlignProperty, Value = TextAlignment.Center
                    },
                },
            };
            var borderWidthLabel = new Label {
                Style = sliderLabelStyle
            };
            var cornerRadiusLabel = new Label {
                Style = sliderLabelStyle
            };                                                                          // new Label { Font = Font.SystemFontOfSize (NamedSize.Micro), YAlign = TextAlignment.Center };
            var heightLabel = new Label {
                Style = sliderLabelStyle
            };                                                                                  // new Label { Font = Font.SystemFontOfSize (NamedSize.Micro), YAlign = TextAlignment.Center };
            var widthLabel = new Label {
                Style = sliderLabelStyle
            };                                                                  // new Label { Font = Font.SystemFontOfSize (NamedSize.Micro), YAlign = TextAlignment.Center };

            this.Content = new ScrollView {
                Content = new StackLayout {
                    Padding  = new Thickness(4d, 4d, 4d, 4d),
                    Spacing  = 4d,
                    Children =
                    {
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Arrow Direction", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                arrowDirectionPicker,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Has Shadow", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                shadowSwitch,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Fill Color", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                fillColorPicker,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Gradient Color", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                gradientColorPicker,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Border Color", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                borderColorPicker,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Border Width", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                borderWidthLabel,
                                borderWidthSlider,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Corner Radius", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                cornerRadiusLabel,
                                cornerRadiusSlider,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Width", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                widthLabel,
                                widthSlider,
                            }
                        },
                        new StackLayout   {
                            Orientation = StackOrientation.Horizontal,
                            Children    =
                            {
                                new Label {
                                    Text = "Height", HorizontalOptions = LayoutOptions.FillAndExpand, YAlign = TextAlignment.Center
                                },
                                heightLabel,
                                heightSlider,
                            }
                        },
                        new BoxView       {
                            HeightRequest = 12d
                        },                                                           // For some additional spacing
                        bubble,
                    },
                }
            };

            bubble.SetBinding(VectorSpeechBubble.FillColorProperty, new Binding("SelectedColor", BindingMode.OneWay, source: fillColorPicker));
            bubble.SetBinding(VectorSpeechBubble.GradientFillColorProperty, new Binding("SelectedColor", BindingMode.OneWay, source: gradientColorPicker));
            bubble.SetBinding(VectorSpeechBubble.BorderColorProperty, new Binding("SelectedColor", BindingMode.OneWay, source: borderColorPicker));
            bubble.SetBinding(VectorSpeechBubble.BorderWidthProperty, new Binding("Value", BindingMode.TwoWay, source: borderWidthSlider));
            bubble.SetBinding(VectorSpeechBubble.CornerRadiusProperty, new Binding("Value", BindingMode.TwoWay, source: cornerRadiusSlider));

            bubble.SetBinding(VectorSpeechBubble.WidthRequestProperty, new Binding("Value", BindingMode.TwoWay, source: widthSlider));
            bubble.SetBinding(VectorSpeechBubble.HeightRequestProperty, new Binding("Value", BindingMode.TwoWay, source: heightSlider));
            bubble.SetBinding(VectorSpeechBubble.HasShadowProperty, new Binding("IsToggled", BindingMode.TwoWay, source: shadowSwitch));

            borderWidthLabel.SetBinding(Label.TextProperty, new Binding("Value", BindingMode.OneWay, source: borderWidthSlider, stringFormat: "{0:0.0}"));
            cornerRadiusLabel.SetBinding(Label.TextProperty, new Binding("Value", BindingMode.OneWay, source: cornerRadiusSlider, stringFormat: "{0:0.0}"));
            heightLabel.SetBinding(Label.TextProperty, new Binding("Value", BindingMode.OneWay, source: heightSlider));
            widthLabel.SetBinding(Label.TextProperty, new Binding("Value", BindingMode.OneWay, source: widthSlider));
        }
Example #2
0
        public ChatPage()
        {
            this.SampleResponses = new List <string> {
                "Well, anything is possible.  Don't you think?",
                "Yes",
                "Maybe",
                "Are we still talking about that?",
                "Let's see how it unfolds",
                "Everything will be alright in the end, and if its not alright, then its not the end",
                "WTF!",
                "LOL",
                "Anything is possible",
                "The only way to play the game is not to play at all",
            };

            Title = "Chat Sample";

            var otherSpeechBubbleStyle = new Style(typeof(VectorSpeechBubble))
            {
                Setters =
                {
                    // new Setter { Property = VectorSpeechBubble.ArrowDirectionProperty, Value = ArrowDirections.LeftBottom },
                    // new Setter { Property = VectorSpeechBubble.HasShadowProperty, Value = true }, // Looks better without
                    new Setter {
                        Property = VectorSpeechBubble.FillColorProperty, Value = ColorHelper.MyLightBlue.ToFormsColor()
                    },
                    new Setter {
                        Property = View.HorizontalOptionsProperty, Value = LayoutOptions.Start
                    },
                }
            };

            var selfSpeechBubbleStyle = new Style(typeof(VectorSpeechBubble))
            {
                Setters =
                {
                    // This is not working in a style (not sure why!)  Manually setting it in the controls for now
                    // new Setter { Property = VectorSpeechBubble.ArrowDirectionProperty, Value = ArrowDirections.RightBottom },
                    // new Setter { Property = VectorSpeechBubble.HasShadowProperty, Value = true }, // Looks better without
                    new Setter {
                        Property = VectorSpeechBubble.FillColorProperty, Value = ColorHelper.MyLightGray.ToFormsColor()
                    },
                    new Setter {
                        Property = View.HorizontalOptionsProperty, Value = LayoutOptions.End
                    },
                }
            };

            this.Resources = new ResourceDictionary();
            this.Resources.Add("OtherSpeechBubbleStyle", otherSpeechBubbleStyle);
            this.Resources.Add("SelfSpeechBubbleStyle", selfSpeechBubbleStyle);

            // Our chat bubbles will get added to this stack layout
            var bubbleStackLayout = new StackLayout {
                Padding  = new Thickness(4d, 4d, 4d, 4d),
                Children =
                {
                    new VectorSpeechBubble {
                        Text           = "Hello my friend! Its so good to chat to you :)",
                        Style          = otherSpeechBubbleStyle,
                        ArrowDirection = ArrowDirections.LeftBottom,
                    },
                    new VectorSpeechBubble {
                        Text           = "Hey. How are ya?",
                        Style          = selfSpeechBubbleStyle,
                        ArrowDirection = ArrowDirections.RightBottom,
                    },
                    (_lastBubble = new VectorSpeechBubble{
                        Text = "Couldn't be better, thanks for asking",
                        Style = otherSpeechBubbleStyle,
                        ArrowDirection = ArrowDirections.LeftBottom,
                    }),
                },
            };

            var textEntryPanel = new TextEntryPanel {
                EnterButtonText = "Say it!", Placeholder = "Something to say?"
            };

            var mainLayout = new RelativeLayout();

            // Scroll view fills up the entire space (including under the text input panel)
            // var innerScrollView = new ScrollView { Content = bubbleStackLayout };
            mainLayout.Children.Add(bubbleStackLayout,
                                    Constraint.Constant(0),
                                    Constraint.Constant(0),
                                    Constraint.RelativeToParent(parent => {
                return(parent.Width);
            }),
                                    Constraint.RelativeToParent(parent => {
                return(parent.Height - textEntryPanel.Height);
            })
                                    );

            // Text input panel pinned to the bottom of the screen
            mainLayout.Children.Add(textEntryPanel,
                                    xConstraint: Constraint.Constant(0),
                                    yConstraint: Constraint.RelativeToParent(parent => {
                System.Diagnostics.Debug.WriteLine("Y constraint = {0}", parent.Height - textEntryPanel.Height);
                return(parent.Height - textEntryPanel.Height);
            }),
                                    widthConstraint: Constraint.RelativeToParent(parent => parent.Width)
                                    );

            // A second scroll view is required here and appears to work, despite recommendations not to use two scroll views (of the same direction together)
            // Without the second scroll view, the keyboard will rise up and cover the text input box.
            // Adding the second scroll view causes the text input to remain visible when the keyboard is displayed

            var outerScrollView = new ScrollView {
                VerticalOptions   = LayoutOptions.Fill,
                HorizontalOptions = LayoutOptions.Fill,
                Content           = mainLayout,
            };

            this.Content = outerScrollView;

            textEntryPanel.Focused += (sender, e) => {
                System.Diagnostics.Debug.WriteLine("textEntryPanel.Focused event fired");

                /*
                 * Unfortunately this fires when the keyboard has only just started to appear, so scrolling something into view now,
                 * causes it to be covered by the keyboard
                 * if (_lastBubble != null) {
                 *      innerScrollView.ScrollToAsync(_lastBubble, ScrollToPosition.MakeVisible, animated:true);
                 * }*/

                // TODO: Scroll theh main scrollview (with the bubbles) into view
                // Somehow lock the secondary scroll view so that the text Entry field can't be scrolled off screen
            };

            textEntryPanel.TextEntered += (sender, e) => {
                if (!string.IsNullOrEmpty(e.Text))
                {
                    bubbleStackLayout.Children.Add(_lastBubble = new VectorSpeechBubble {
                        Text           = e.Text,
                        Style          = selfSpeechBubbleStyle,
                        ArrowDirection = ArrowDirections.RightBottom
                    });

                    // After random time, the other person starts typing
                    Device.StartTimer(TimeSpan.FromSeconds(_random.NextDouble() * 1d), () => {
                        var newBubble = new VectorSpeechBubble {
                            Style          = otherSpeechBubbleStyle,
                            ArrowDirection = ArrowDirections.LeftBottom,
                            IsTyping       = true,
                        };
                        bubbleStackLayout.Children.Add(newBubble);
                        // After a further random period, the text becomes visible as they finish typing
                        Device.StartTimer(TimeSpan.FromSeconds(_random.NextDouble() * 3d), () => {
                            newBubble.Text     = PickRandomResponse();
                            newBubble.IsTyping = false;
                            return(false);
                        });
                        return(false);
                    });
                }
            };
        }
Example #3
0
		public ChatPage ()
		{
			this.SampleResponses = new List<string> {
				"Well, anything is possible.  Don't you think?",
				"Yes",
				"Maybe",
				"Are we still talking about that?",
				"Let's see how it unfolds",
				"Everything will be alright in the end, and if its not alright, then its not the end",
				"WTF!",
				"LOL",
				"Anything is possible",
				"The only way to play the game is not to play at all",
			};

			Title = "Chat Sample";

			var otherSpeechBubbleStyle = new Style (typeof(VectorSpeechBubble)) {
				Setters = {
					// new Setter { Property = VectorSpeechBubble.ArrowDirectionProperty, Value = ArrowDirections.LeftBottom },
					// new Setter { Property = VectorSpeechBubble.HasShadowProperty, Value = true }, // Looks better without
					new Setter { Property = VectorSpeechBubble.FillColorProperty, Value = ColorHelper.MyLightBlue.ToFormsColor() },
					new Setter { Property = View.HorizontalOptionsProperty, Value = LayoutOptions.Start },
				}};
					
			var selfSpeechBubbleStyle = new Style (typeof(VectorSpeechBubble)) { 
				Setters = {
					// This is not working in a style (not sure why!)  Manually setting it in the controls for now
					// new Setter { Property = VectorSpeechBubble.ArrowDirectionProperty, Value = ArrowDirections.RightBottom },
					// new Setter { Property = VectorSpeechBubble.HasShadowProperty, Value = true }, // Looks better without
					new Setter { Property = VectorSpeechBubble.FillColorProperty, Value = ColorHelper.MyLightGray.ToFormsColor() },
					new Setter { Property = View.HorizontalOptionsProperty, Value = LayoutOptions.End },
				}};

			this.Resources = new ResourceDictionary ();
			this.Resources.Add ("OtherSpeechBubbleStyle", otherSpeechBubbleStyle);
			this.Resources.Add ("SelfSpeechBubbleStyle", selfSpeechBubbleStyle);

			// Our chat bubbles will get added to this stack layout
			var bubbleStackLayout = new StackLayout { 
				Padding = new Thickness(4d,4d,4d,4d),
				Children = {
					new VectorSpeechBubble {
						Text = "Hello my friend! Its so good to chat to you :)",
						Style = otherSpeechBubbleStyle,
						ArrowDirection = ArrowDirections.LeftBottom,
					},
					new VectorSpeechBubble {
						Text = "Hey. How are ya?",
						Style = selfSpeechBubbleStyle,						
						ArrowDirection = ArrowDirections.RightBottom,
					},
					(_lastBubble = new VectorSpeechBubble {
						Text = "Couldn't be better, thanks for asking",
						Style = otherSpeechBubbleStyle,
						ArrowDirection = ArrowDirections.LeftBottom,
					}),
				},
			};
				
			var textEntryPanel = new TextEntryPanel { EnterButtonText = "Say it!", Placeholder = "Something to say?"};

			var mainLayout = new RelativeLayout ();
			// Scroll view fills up the entire space (including under the text input panel)
			// var innerScrollView = new ScrollView { Content = bubbleStackLayout };
			mainLayout.Children.Add (bubbleStackLayout,
				Constraint.Constant (0),
				Constraint.Constant (0),
				Constraint.RelativeToParent (parent => {
					return parent.Width;
				}),
				Constraint.RelativeToParent (parent => {
					return parent.Height - textEntryPanel.Height;
				})
			);

			// Text input panel pinned to the bottom of the screen
			mainLayout.Children.Add (textEntryPanel,
				xConstraint: Constraint.Constant (0),
				yConstraint: Constraint.RelativeToParent (parent => { 
					System.Diagnostics.Debug.WriteLine ("Y constraint = {0}", parent.Height - textEntryPanel.Height);
					return parent.Height - textEntryPanel.Height; 
				}),
				widthConstraint: Constraint.RelativeToParent (parent => parent.Width)
			);

			// A second scroll view is required here and appears to work, despite recommendations not to use two scroll views (of the same direction together)
			// Without the second scroll view, the keyboard will rise up and cover the text input box.
			// Adding the second scroll view causes the text input to remain visible when the keyboard is displayed

			var outerScrollView = new ScrollView {
				VerticalOptions = LayoutOptions.Fill,
				HorizontalOptions = LayoutOptions.Fill,
				Content = mainLayout,
			};

			this.Content = outerScrollView;

			textEntryPanel.Focused += (sender, e) => {
				System.Diagnostics.Debug.WriteLine("textEntryPanel.Focused event fired");
				/*
				 * Unfortunately this fires when the keyboard has only just started to appear, so scrolling something into view now,
				 * causes it to be covered by the keyboard
				if (_lastBubble != null) {
					innerScrollView.ScrollToAsync(_lastBubble, ScrollToPosition.MakeVisible, animated:true);
				}*/

				// TODO: Scroll theh main scrollview (with the bubbles) into view
				// Somehow lock the secondary scroll view so that the text Entry field can't be scrolled off screen
			};

			textEntryPanel.TextEntered += (sender, e) => {
				if (!string.IsNullOrEmpty(e.Text)) {
					bubbleStackLayout.Children.Add(_lastBubble = new VectorSpeechBubble{ 
						Text = e.Text,
						Style = selfSpeechBubbleStyle,
						ArrowDirection = ArrowDirections.RightBottom });

					// After random time, the other person starts typing
					Device.StartTimer(TimeSpan.FromSeconds(_random.NextDouble()*1d), () => {
						var newBubble = new VectorSpeechBubble {
							Style = otherSpeechBubbleStyle,
							ArrowDirection = ArrowDirections.LeftBottom,
							IsTyping = true,
						};
						bubbleStackLayout.Children.Add(newBubble);
						// After a further random period, the text becomes visible as they finish typing
						Device.StartTimer(TimeSpan.FromSeconds(_random.NextDouble()*3d), () => {
							newBubble.Text = PickRandomResponse();
							newBubble.IsTyping = false;
							return false;
						});
						return false;
					});
				}
			};
		}