How to create a speech bubble in UWP?

后端 未结 2 1106
别那么骄傲
别那么骄傲 2020-12-10 18:00

I\'m creating a chat application and would like to create the typical speech bubble that contains each message. I created a Path object in Blend (in XAML) like this:

相关标签:
2条回答
  • 2020-12-10 18:07

    You may use Polygon in combination with StackPanel:

    <StackPanel Orientation="Horizontal"
                HorizontalAlignment="Left"
                Padding="6"
                >
        <Polygon Points="0,0 15,0 15,15"
                 Fill="LightGray"
                 Margin="0,10,0,0"
                 />
    
        <Border Background="LightGray"
                CornerRadius="3"
                Padding="6"
                VerticalAlignment="Top"
                >
            <TextBlock Text="Text"
                       TextWrapping="WrapWholeWords"
                       Width="100"
                       Height="50"
                       />
        </Border>
    </StackPanel>
    

    which looks like this:

    EDIT:

    Version with border:

    <Grid HorizontalAlignment="Left"
          Padding="6"
          >
        <Polygon Points="0,0 15,0 15,15"
                 Fill="LightGray"
                 Stroke="Black"
                 Margin="0,10,0,0"
                 />
    
        <Border Background="LightGray"
                BorderBrush="Black"
                BorderThickness="0.5"
                CornerRadius="3"
                Padding="6"
                Margin="14,0,0,0"
                VerticalAlignment="Top"
                >
            <TextBlock Text="Text"
                       TextWrapping="WrapWholeWords"
                       Width="100"
                       Height="50"
                       />
        </Border>
    
        <Polygon Points="0,0 15,0 15,15"
                 Fill="LightGray"
                 Margin="0,10,0,0"
                 />
    </Grid>
    

    This is probably not the easiest and the best way how to do this, maybe Path will be better to do this, but it works:

    0 讨论(0)
  • 2020-12-10 18:28

    Here is a Custom control that declares a Dependency Property for the Text and reuse some properties of the base control in its template (Background, Width, Heigth).

    First the class definition: (SpeechBubbleControl.xaml.cs)

    [TemplatePart(Name = PartBubbleText, Type = typeof(TextBlock))]
    public sealed partial class SpeechBubbleControl : Control
    {
        private const string PartBubbleText = "BubbleText";
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(nameof(Text), typeof(string), typeof(SpeechBubbleControl), new PropertyMetadata(""));
    
        public SpeechBubbleControl()
        {
            DefaultStyleKey = typeof(SpeechBubbleControl);
        }
    
        public string Text
        {
            get { return GetValue(TextProperty).ToString(); }
            set { SetValue(TextProperty, value); }
        } 
    }
    

    With its default template (SpeechBubbleControl.xaml):

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:local="using:App6"
                        >
    
        <Style TargetType="local:SpeechBubbleControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:SpeechBubbleControl">
                        <Grid Background="{TemplateBinding Background}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>
                            <Rectangle Fill="{TemplateBinding Background}" Stroke="#FF000000" RadiusX="10" RadiusY="10"/>
                            <Path Fill="{TemplateBinding Background}" Stretch="Fill" Stroke="#FF000000" HorizontalAlignment="Left" Margin="-15,-5,0,20" Width="30" Height="40" Data="M0,0 L15,40 30,20 0,0" RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False">
                                <Path.RenderTransform>
                                    <CompositeTransform Rotation="-20"/>
                                </Path.RenderTransform>
                            </Path>
                            <Rectangle Fill="{TemplateBinding Background}" RadiusX="10" RadiusY="10" Margin="1"/>
                            <TextBlock Name="BubbleText" HorizontalAlignment="Center" VerticalAlignment="Center" 
                                       Text="{TemplateBinding Text}" FontSize="20" TextWrapping="Wrap"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    

    You have to import this resource into your application resource using something like this in your app.xaml:

    <Application
        x:Class="App6.App"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App6"
        RequestedTheme="Light">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="SpeechBubbleControl.xaml" />
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    And finally a sample test page, which use this control with bindings on width, height (based on the sliders) and the text that must be displayed.

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="40"/>
                <RowDefinition Height="40"/>
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBox x:Name="testText" Grid.ColumnSpan="2"  PlaceholderText="My text..." />
            <Slider x:Name="width" Grid.Row="1" Minimum="50" Maximum="500" Value="200" />
            <Slider x:Name="height" Grid.Row="1"  Grid.Column="2" Minimum="50" Maximum="500" Value="100" />
    
            <local:SpeechBubbleControl Grid.Row="2" Grid.ColumnSpan="2"
                                       Width="{Binding Value, ElementName=width}"
                                       Height="{Binding Value, ElementName=height}" 
                                       Text="{Binding Text, ElementName=testText, FallbackValue=Hello}"
                                       Background="Beige" >
            </local:SpeechBubbleControl>
        </Grid>
    
        <local:SpeechBubbleControl Grid.Row="2" Grid.ColumnSpan="2"
            Width="{Binding Value, ElementName=width}" Height="{Binding Value, ElementName=height}" 
                                   Text="{Binding Text, ElementName=testText, FallbackValue=Hello}"
                                   Background="Beige" >
    
        </local:SpeechBubbleControl>
    </Grid>
    

    Here is the result:

    Note that my answer is adapted from this one: WPF speech bubble

    0 讨论(0)
提交回复
热议问题