title author date CreateTime categories
win10 uwp 气泡
lindexi
2018-08-10 19:16:50 +0800
2018-2-13 17:23:3 +0800
Win10 UWP

如果做聊天工具,需要气泡。
本文,如果写一个气泡控件需要如何做

## WPF 气泡

先说如何在 WPF 做一个气泡。

可以看到,气泡就是一个和 Grid 差不多的东西,只是有边框,边框是一个气泡

如何去写一个外框?

可以新建一个类,继承 Decorator ,就可以啦

现在的难点是如何获得子元素的大小。

可以看到一个气泡是尖的气泡和一个矩形组成

我做了一些修改,先做一个像这样的气泡

气泡分为两部分,一个是尖头一个矩形

可以看到,尖头大小可以固定,但是矩形必须使用子控件的大小

于是先假如子元素的宽度是100,高度 50 ,这样来画一个气泡。

如何画一个三角?

假设尖头宽度 10 高度 5 ,那么可以看到第一个点是 (0,5) 第二个点是 (5,0) 第三个点是 (10,5)

需要知道, WPF 使用的布局不是和以前课本说的一样

但是除了尖头,还需要添加矩形的距离

添加的距离是矩形宽度的一半减去5,看到这里一般不会觉得有困难。

于是添加到实际的值,这里矩形宽度为 100 于是最后的值就是 (45,5) ,第二个点是 (50,0) 第三个点是 (55,5)

接下来就是计算矩形的值,矩形的值就是 x=0 y=5 ,宽度 100 高度 50

计算出来,就需要画出来。

PathFigure 可以画线,也就是通过他给他三个点就好

把上面的几个点写出来

                            new PathFigure
{
IsClosed = false,
StartPoint = new Point(45, 5),
Segments = new PathSegmentCollection()
{
new LineSegment(new Point(50), 0), true),
new LineSegment(new Point(55, 5), true)
}
}

但需要把三角加到 PathGeometry 才可以显示

                    Geometry1 = new PathGeometry()
{
Figures = new PathFigureCollection()
{
new PathFigure
{
IsClosed = false,
StartPoint = new Point(45, 5),
Segments = new PathSegmentCollection()
{
new LineSegment(new Point(50), 0), true),
new LineSegment(new Point(55, 5), true)
}
}
}
}

这样写在界面path,可以看到显示出来三角形,因为没有设置线条,所以没有把鼠标移到三角是看不到的

接着需要画矩形

                        Geometry2 = new RectangleGeometry(new Rect(0, 5, 100,
50)
, 0, 0)

但是如何直接把两个显示,看起来是不对的,因为是一个矩形和三角,不是气泡

所以组合一下图形就好

                 var cg = new CombinedGeometry
{
Geometry1 ,
Geometry2 ,
GeometryCombineMode = GeometryCombineMode.Xor
};

但是实际需要获得子元素的大小,也需要显示,那么显示可以先重写 OnRender

从 OnRender 画出的方法很简单

                GuidelineSet guideLines = new GuidelineSet();
drawingContext.PushGuidelineSet(guideLines);
drawingContext.DrawGeometry(brush, pen, cg);

其中的 颜色自己定义,cg就是上面的图形。

但是这样的自定义控件需要设置宽高,如何使用子元素的宽高加上自己的padding?

如果只是重新显示,那么界面是不知道气泡的大小,所以得到的是没显示,为了让气泡可以显示,先给他一个宽高,这样就可以演示。

但是我需要直接就写如何获取子元素的大小,把他作为气泡的大小。

获取子元素可以通过重写 MeasureOverride

第一步,测量子元素,通过子元素可以获得高度宽度

                    Child.Measure(constraint);

定义自己的 padding ,这个值先随意给,表示气泡离元素距离

那么计算得到自己的大小就是 子元素的宽高加上 padding 加上气泡需要的外框

因为对于高度,需要加上气泡的高度 5 才可以,代码很容易就看懂,我就不说啦

        protected override Size MeasureOverride(Size constraint)
{
Thickness padding = Padding;
Size result = new Size();
if (Child != null)
{
//测量子控件的大小
Child.Measure(constraint); result.Width = Child.DesiredSize.Width + padding.Left + padding.Right;
result.Height = Child.DesiredSize.Height + padding.Top + padding.Bottom + 5;
}
return result;
}

拿到了子控件的高度,还需要重写自己的布局

            protected override Size ArrangeOverride(Size arrangeSize)
{
Thickness padding = Padding;
if (Child != null)
{
Size result = new Size();
Child.Arrange(new Rect(new Point(padding.Left, 5 + padding.Top), Child.DesiredSize));
result.Width = Child.DesiredSize.Width + padding.Left + padding.Right;
result.Height = Child.DesiredSize.Height + padding.Top + padding.Bottom + 5;
return result;
}
return arrangeSize;
}

这里出现很多个 5 ,意思就是气泡高度,为了设置气泡高度,所以给他一个属性。

         public double HeadHeight
{
get
{
return (double)GetValue(HeadHeightProperty);
}
set
{
SetValue(HeadHeightProperty, value);
}
} /// <summary>
/// 标识 <see cref="HeadHeight" /> 的依赖项属性。
/// </summary>
public static readonly DependencyProperty HeadHeightProperty = DependencyProperty.Register(
"HeadHeight", typeof(double), typeof(PeakedAdorner), new PropertyMetadata(5d));

现在可以修改一下代码,让他可以自动适应

矩形的宽高可以通过自己的大小计算

    Geometry2 = new RectangleGeometry(new Rect(0, HeadHeight, ActualWidth,
ActualHeight - HeadHeight)
, 0, 0)

可以看到 坐标没有变化,有变化的是高度,宽度,可以通过获得自己的大小设置,因为在计算大小已经从子元素加上自己的需要大小,所以得到的大小可以设置

那么现在的 OnRender 可以写为

            protected override void OnRender(DrawingContext drawingContext)
{ Pen pen = new Pen();
pen.Brush = BorderBrush;
pen.Thickness = BorderThickness; var leftpad = (ActualWidth - HeadWidth) / 2;
var cg = new CombinedGeometry
{
Geometry1 = new PathGeometry()
{
Figures = new PathFigureCollection()
{
new PathFigure
{
IsClosed = false,
StartPoint = new Point(leftpad, HeadHeight),
Segments = new PathSegmentCollection()
{
new LineSegment(new Point(leftpad + (HeadWidth / 2), 0), true),
new LineSegment(new Point(leftpad + HeadWidth, HeadHeight), true)
}
}
}
},
Geometry2 = new RectangleGeometry(new Rect(0, HeadHeight, ActualWidth,
ActualHeight - HeadHeight)
, 0, 0),
GeometryCombineMode = GeometryCombineMode.Xor
}; GuidelineSet guideLines = new GuidelineSet();
drawingContext.PushGuidelineSet(guideLines);
drawingContext.DrawGeometry(Background, pen, cg); }

BorderBrush 也是自己设置的 ,BorderThickness 也是,于是继续设置背景色 Background 和其它的如圆角

现在看起来的属性是

         public static readonly DependencyProperty BackgroundProperty =
DependencyProperty.Register("Background", typeof(Brush), typeof(PeakedAdorner)
, new PropertyMetadata(new SolidColorBrush(Color.FromRgb(255, 255, 255)))); public static readonly DependencyProperty PaddingProperty =
DependencyProperty.Register("Padding", typeof(Thickness), typeof(PeakedAdorner)
, new PropertyMetadata(new Thickness(10, 5, 10, 5))); public static readonly DependencyProperty BorderBrushProperty =
DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(PeakedAdorner)
, new PropertyMetadata(new SolidColorBrush(Colors.Black))); public static readonly DependencyProperty BorderThicknessProperty =
DependencyProperty.Register("BorderThickness", typeof(double), typeof(PeakedAdorner),
new PropertyMetadata(1d)); /// <summary>
/// 标识 <see cref="HeadWidth" /> 的依赖项属性。
/// </summary>
public static readonly DependencyProperty HeadWidthProperty = DependencyProperty.Register(
"HeadWidth", typeof(double), typeof(PeakedAdorner), new PropertyMetadata(0d)); /// <summary>
/// 标识 <see cref="HeadHeight" /> 的依赖项属性。
/// </summary>
public static readonly DependencyProperty HeadHeightProperty = DependencyProperty.Register(
"HeadHeight", typeof(double), typeof(PeakedAdorner), new PropertyMetadata(5d)); public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius)
, typeof(PeakedAdorner), new PropertyMetadata(new CornerRadius(0))); /// <summary>
/// 背景色
/// </summary>
public Brush Background
{
get
{
return (Brush)GetValue(BackgroundProperty);
}
set
{
SetValue(BackgroundProperty, value);
}
} /// <summary>
/// 内边距
/// </summary>
public Thickness Padding
{
get
{
return (Thickness)GetValue(PaddingProperty);
}
set
{
SetValue(PaddingProperty, value);
}
} /// <summary>
/// 边框颜色
/// </summary>
public Brush BorderBrush
{
get
{
return (Brush)GetValue(BorderBrushProperty);
}
set
{
SetValue(BorderBrushProperty, value);
}
} /// <summary>
/// 边框大小
/// </summary>
public double BorderThickness
{
get
{
return (double)GetValue(BorderThicknessProperty);
}
set
{
SetValue(BorderThicknessProperty, value);
}
} /// <summary>
/// 获取或设置尖角width
/// </summary>
public double HeadWidth
{
get
{
return (double)GetValue(HeadWidthProperty);
}
set
{
SetValue(HeadWidthProperty, value);
}
} /// <summary>
/// 获取或设置尖角
/// </summary>
public double HeadHeight
{
get
{
return (double)GetValue(HeadHeightProperty);
}
set
{
SetValue(HeadHeightProperty, value);
}
} /// <summary>
/// 边框大小
/// </summary>
public CornerRadius CornerRadius
{
get
{
return (CornerRadius)GetValue(CornerRadiusProperty);
}
set
{
SetValue(CornerRadiusProperty, value);
}
}

如何使用?

            <local:PeakedAdorner CornerRadius="5" Margin="0,0,0.4,-0.2" >
<TextBlock Text="林德熙"></TextBlock>
</local:PeakedAdorner>

这样就好了,里面的控件可以是任何的,你想要的,如Grid ,textBox

现在看起来就是这样

这样就做好气泡,如果需要气泡显示在其他的,那么可以通过自己计算,所有的值需要放在哪

2018-8-10-win10-uwp-气泡的更多相关文章

  1. win10 uwp 使用 Microsoft.Graph 发送邮件

    在 2018 年 10 月 13 号参加了 张队长 的 Office 365 训练营 学习如何开发 Office 365 插件和 OAuth 2.0 开发,于是我就使用 UWP 尝试使用 Micros ...

  2. Win10 UWP开发实现Bing翻译

    微软在WP上的发展从原来的Win7到Win8,Win8.1,到现在的Win10 UWP,什么是UWP,UWP即Windows 10 中的Universal Windows Platform简称.即Wi ...

  3. Win10/UWP开发—使用Cortana语音与App后台Service交互

    上篇文章中我们介绍了使用Cortana调用前台App,不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互,这篇我们讲讲如何使用Cortana调用App的后台任务,相比 ...

  4. Win10 UWP应用发布流程

    简介 Win10 UWP应用作为和Win8.1 UAP应用不同的一种新应用形式,其上传至Windows应用商店的流程也有了一些改变. 这篇博文记录了我们发布一款Win10 UWP应用的基本流程,希望为 ...

  5. win10 uwp 列表模板选择器

    本文主要讲ListView等列表可以根据内容不同,使用不同模板的列表模板选择器,DataTemplateSelector. 如果在 UWP 需要定义某些列的显示和其他列不同,或者某些行的显示和其他行不 ...

  6. win10 uwp 获得元素绝对坐标

    有时候需要获得一个元素,相对窗口的坐标,在修改他的位置可以使用. 那么 UWP 如何获得元素坐标? 我提供了一个方法,可以获得元素的坐标. 首先需要获得元素,如果没有获得元素,那么如何得到他的坐标? ...

  7. win10 uwp 毛玻璃

    毛玻璃在UWP很简单,不会和WPF那样伤性能. 本文告诉大家,如何在 UWP 使用 win2d 做毛玻璃. 毛玻璃可以使用 win2D 方法,也可以使用 Compositor . 使用 win2d 得 ...

  8. win10 uwp 读取保存WriteableBitmap 、BitmapImage

    我们在UWP,经常使用的图片,数据结构就是 BitmapImage 和 WriteableBitmap.关于 BitmapImage 和 WriteableBitmap 区别,我就不在这里说.主要说的 ...

  9. 【广告】win10 uwp 水印图床 含代码

    本文主要是广告我的软件. 图床可以加速大家写博客上传图片的时间,通过简化我们的操作来得到加速. 在写博客的时候,我们发现,我们需要上传一张图片,需要先打开图片,然后选择本地图片,然后上传. 但是我经常 ...

  10. win10 uwp 商业游戏 1.2.1

    上一个游戏已经告诉大家如何写多个游戏,现在继续写这个无聊的游戏 希望大家在看这篇文章之前先看win10 uwp 商业游戏,在这个文章告诉了大家如何创建游戏. 修改数值 可以从上一篇的博客的游戏看到升级 ...

随机推荐

  1. 15-vim-缩排和重复执行

    缩排和重复执行 命令 功能 >> 向右增加缩进 << 向左减少缩进 . 重复上次命令 缩排命令在开发程序时,统一增加代码的缩进比较有用! 一次性在选中代码前增加4个空格,就叫做 ...

  2. 装Windows和Linux双系统

    Windows 7 + Linux mint 装来玩玩呗,好歹算是IT男 我电脑本来就是Windows 7 然后用软碟通做个Linux的启动盘 注意“便捷启动”要选syslinux 然后从U盘启动会进 ...

  3. ollvm 使用——“Cannot open /dev/random”错误的解决方法

    找到 \obfuscator-llvm-4.0\lib\Transforms\Obfuscation\CryptoUtils.cpp 这个文件, 新增两个头文件 #include <window ...

  4. (转)Unity Cinemachine插件,实现单目标和多目标之间切换

    Unity Cinemachine插件学习笔记,实现单目标和多目标之间切换*版本要求Unity2017.1及以上. 参考资料: [官方] Unity 2017.1正式版发布 Cinemachine插件 ...

  5. 【javascript闭包】转载一篇不错的解释,也有几个大牛的链接

    初学闭包时一直以为很简单.但伴随对一个问题深入学习后,才算真正理解了闭包,同时也发现连<<JavaScript高级程序设计>>中都些不准确的地方. 我不准备从头介绍闭包的概念, ...

  6. oracle入门学习之oracle数据库结构

    1. oracle数据库结构 1.1 Oracle可以看做是一个大的数据库???,里面可以创建很多实例; 一个实例对应多个表空间.多个用户; 一个用户只能有一个表空间; 一个表空间可以有多个用户; 一 ...

  7. java -jar 设置日志位置

    使用 java -jar形式启动,设定日志的位置 语法如下: java -jar xxx.jar > xxx.log References java -jar 设置日志位置

  8. 富文本 保存转义StringEscapeUtils.unescapeHtml4(

    StringEscapeUtils.unescapeHtml4( [org.apache.commons.lang.StringEscapeUtils.escapeHtml(str)] [String ...

  9. LOJ6485 LJJ 学二项式定理 解题报告

    LJJ 学二项式定理 题意 \(T\)组数据,每组给定\(n,s,a_0,a_1,a_2,a_3\),求 \[ \sum_{i=0}^n \binom{n}{i}s^ia_{i\bmod 4} \] ...

  10. Android中attrs.xml文件的使用详解

    $*********************************************************************************************$ 博主推荐 ...