Как создать речевой пузырь в UWP?

Я создаю приложение чата и хотел бы создать типичный речевой пузырь, который содержит каждое сообщение. Я создал объект Path в Blend (в XAML) следующим образом:

enter image description here

проблема в том, что путь разработан, чтобы иметь заданную ширину и высоту, и я хотел бы это обернуть вокруг текста без растяжения, поэтому он не будет выглядеть деформированным,как граница.

Как я могу заставить его вести себя так, как я хочешь?

2 ответов


вы можете использовать Polygon в сочетании с 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>

выглядит так:

Screenshot 1

EDIT:

версия с границами:

<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>

это, вероятно, не самый простой и лучший способ, как это сделать, может быть Path будет лучше сделать это, но это работает:

Screenshot 2


вот пользовательский элемент управления, который объявляет свойство зависимостей для текста и повторно использует некоторые свойства базового элемента управления в его шаблоне (фон, ширина, высота).

сначала определение класса: (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); }
    } 
}

с шаблоном по умолчанию (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>

вы должны импортировать этот ресурс в свой ресурс приложения, используя что-то вроде этого в вашем 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>

и, наконец, пример тестовой страницы, которая используйте этот элемент управления, с привязками по ширине, высоте (на ползунки) и текст, который должен отображаться.

<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>

вот результат:

Final result: bubble with basic binding test

обратите внимание, что мой ответ взят из этого: WPF речи пузырь