原文:WPF系列教程——(一)仿TIM QQ界面 - 简书

TIM QQ

我们先来看一下TIM QQ长什么样,整体可以将界面分为三个部分

 
TIM QQ

1. 准备

  • 阅读本文假设你已经有XAML布局的基础,所以只对部分布局进行说明。
  • 界面上的图标均来自 Material Design Icons
    选择需要的图标后点击View XAML

     
    图片.png

    会显示WPF的调用代码,直接复制到项目中即可,WPF是支持矢量图显示的。

     
    图片.png
  • 本文中的控件使用了开源的MaterialDesignInXamlToolkit,这是一款WPF的Material Design UI库,也是WPF最流行的UI库之一,可以轻松的做出漂亮的界面,到NuGet中搜索即可添加到项目。

     
    NuGet

    App.xaml文件中,添加以下代码,应用资源样式
    <SolidColorBrush x:Key="PrimaryHueMidBrush" Color="#1C93EC" /> Color表示所有控件的主题颜色,不添加的话所有控件颜色默认为紫色。

 <ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Light.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
<ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="PrimaryHueMidBrush" Color="#1C93EC" />
</ResourceDictionary>

在需要使用MaterialDesignInXamlToolkit控件的页面引入命名空间
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"

  • 使用Grid布局将页面划分为三个区域,感觉Grid是万能布局,可以用它设计出大多数软件90%的界面
 <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="63*" />
<RowDefinition Height="706*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"> </Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="157*" />
<ColumnDefinition Width="389*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0"> </Grid>
<Grid Grid.Column="1"> </Grid>
</Grid>
</Grid>
 
三个区域

2. 圆形头像

在WPF上显示圆形图片很简单,使用Ellipse绘制圆形设置宽和高一致绘制正圆,在内部使用Image笔刷填充图片,本文中的头像显示方式均以此来实现。

<Ellipse Width="50"
Height="50">
<Ellipse.Fill>
<ImageBrush ImageSource="Images/github.png" />
</Ellipse.Fill>
</Ellipse>

3. 工具栏设计

工具栏的三个不同几何图形,使用Polygon来绘制,再将内部填充不同的颜色,坐标自行测试选择适当位置。

 
工具栏

第一个多边形

<Polygon Points="0,0 700,0 756,65 0,65"
StrokeThickness="1">
<Polygon.Fill>
<SolidColorBrush Color="#1C93EC" />
</Polygon.Fill>
</Polygon>

第二个多边形

 <Polygon Points="700,0 780,0 740,50 "
StrokeThickness="1">
<Polygon.Fill>
<SolidColorBrush Color="#3E58C9" />
</Polygon.Fill>
</Polygon>

第三个多边形

 <Polygon Points="780,0 1100,0 1100,65 723,65 "
StrokeThickness="1">
<Polygon.Fill>
<SolidColorBrush Color="#3448A1" />
</Polygon.Fill>
</Polygon>

XAML代码如下,简书没有折叠代码功能啊,这段有点长。

  <materialDesign:ColorZone Mode="PrimaryMid"
Name="NavBar"
Height="65"
MouseLeftButtonDown="NavBar_MouseLeftButtonDown"
materialDesign:ShadowAssist.ShadowDepth="Depth3"> <Grid>
<!--第三个几何图形-->
<Polygon Points="780,0 1100,0 1100,65 723,65 "
StrokeThickness="1">
<Polygon.Fill>
<SolidColorBrush Color="#3448A1" />
</Polygon.Fill>
</Polygon>
<!--第二个几何图形-->
<Polygon Points="700,0 780,0 740,50 "
StrokeThickness="1">
<Polygon.Fill>
<SolidColorBrush Color="#3E58C9" />
</Polygon.Fill>
</Polygon>
<!--第一个几何图形-->
<Polygon Points="0,0 700,0 756,65 0,65"
StrokeThickness="1">
<Polygon.Fill>
<SolidColorBrush Color="#1C93EC" />
</Polygon.Fill>
</Polygon>
<Ellipse Cursor="Hand"
HorizontalAlignment="Left"
Margin="10 5"
Width="50"
Height="50">
<Ellipse.Fill>
<ImageBrush ImageSource="Images/github.png" />
</Ellipse.Fill>
</Ellipse>
<Grid HorizontalAlignment="Center"
Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Button Width="60"
Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="30"
Height="30">
<Canvas Width="24"
Height="24">
<Path Data="M17,12V3A1,1 0 0,0 16,2H3A1,1 0 0,0 2,3V17L6,13H16A1,1 0 0,0 17,12M21,6H19V15H6V17A1,1 0 0,0 7,18H18L22,22V7A1,1 0 0,0 21,6Z"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
<Grid Grid.Column="1">
<Button Width="60"
Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="30"
Height="30">
<Canvas Width="24"
Height="24">
<Path Data="M16.5,12A2.5,2.5 0 0,0 19,9.5A2.5,2.5 0 0,0 16.5,7A2.5,2.5 0 0,0 14,9.5A2.5,2.5 0 0,0 16.5,12M9,11A3,3 0 0,0 12,8A3,3 0 0,0 9,5A3,3 0 0,0 6,8A3,3 0 0,0 9,11M16.5,14C14.67,14 11,14.92 11,16.75V19H22V16.75C22,14.92 18.33,14 16.5,14M9,13C6.67,13 2,14.17 2,16.5V19H9V16.75C9,15.9 9.33,14.41 11.37,13.28C10.5,13.1 9.66,13 9,13Z"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
<Grid Grid.Column="2">
<Button Width="60"
Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="30"
Height="30">
<Canvas Width="24"
Height="24">
<Path Data="M19,16A3,3 0 0,0 22,13A3,3 0 0,0 19,10H17.5V9.5A5.5,5.5 0 0,0 12,4C9.5,4 7.37,5.69 6.71,8H6A4,4 0 0,0 2,12A4,4 0 0,0 6,16V11H18V16H19M19.36,8.04C21.95,8.22 24,10.36 24,13A5,5 0 0,1 19,18H18V22H6V18A6,6 0 0,1 0,12C0,8.91 2.34,6.36 5.35,6.04C6.6,3.64 9.11,2 12,2C15.64,2 18.67,4.6 19.36,8.04M8,13V20H16V13H8M9,18H15V19H9V18M15,17H9V16H15V17M9,14H15V15H9V14Z"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
</Grid>
<Grid HorizontalAlignment="Right"
Width="150">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0">
<Button Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="25"
Height="25">
<Canvas Width="24"
Height="24">
<Path Data="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
<Grid Grid.Column="1">
<Button Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="25"
Height="25">
<Canvas Width="24"
Height="24">
<Path Data="M20,14H4V10H20"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
<Grid Grid.Column="2">
<Button Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="25"
Height="25">
<Canvas Width="24"
Height="24">
<Path Data="M4,4H20V20H4V4M6,8V18H18V8H6Z"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
<Grid Grid.Column="3">
<Button Height="60"
Background="{x:Null}"
BorderBrush="{x:Null}"
materialDesign:ShadowAssist.ShadowDepth="Depth1"
Padding="0">
<Viewbox Width="25"
Height="25">
<Canvas Width="24"
Height="24">
<Path Data="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"
Fill="White" />
</Canvas>
</Viewbox>
</Button>
</Grid>
</Grid> </Grid>
</materialDesign:ColorZone>

4. 好友列表设计

好友列表使用了ListView,效果图中的好友都是静态的数据,列表绑定会在下一节讲到。

 
好友列表
     <Grid Background="#FAFAFA"
Grid.Column="0">
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
Cursor="Hand"> </ListView>
<materialDesign:PopupBox Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}"
PlacementMode="TopAndAlignCentres"
ToolTipService.Placement="Left"
ToolTip="TIM QQ"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="20"> </materialDesign:PopupBox>
</Grid>

ListView中Item代码如下

 <ListViewItem Height="60"
Padding="0">
<StackPanel Orientation="Horizontal"
Margin="10 0">
<Ellipse Cursor="Hand"
Width="50"
Height="50">
<Ellipse.Fill>
<ImageBrush ImageSource="Images/head2.jpg" />
</Ellipse.Fill>
</Ellipse>
<StackPanel Orientation="Vertical"
VerticalAlignment="Center"
Margin="5 0">
<TextBlock FontSize="15"
Foreground="Black"
Text="糖宝" />
<TextBlock Margin="0 2 0 0"
FontSize="12"
Text="Hello world" />
</StackPanel>
</StackPanel>
</ListViewItem>

5. 名片设计

名片页面是不是和TIM QQ的几乎一模一样~

 
名片

XAML代码如下

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Image Stretch="UniformToFill" Source="Images/head1.jpg" />
</Grid>
<Grid Grid.Row="1">
<Button Style="{StaticResource MaterialDesignFloatingActionButton}"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0 -30 5 0" BorderBrush="{x:Null}"
ToolTip="修改资料">
<materialDesign:PackIcon Kind="Pencil"
Height="24"
Width="24" /> </Button> <StackPanel Orientation="Vertical">
<TextBlock Text="Go to hell!"
HorizontalAlignment="Center"
FontSize="35"
Margin="0 20 0 0" />
<StackPanel Orientation="Horizontal"
Margin="80 5 0 0 " >
<TextBlock Text="账号 "
Foreground="#B7B7B7" />
<TextBlock Text="vaemc520@qq.com" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="80 5 0 0 ">
<TextBlock Text="昵称 "
Foreground="#B7B7B7" />
<TextBlock Text="Go to hell!" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="80 5 0 0 ">
<TextBlock Text="手机 "
Foreground="#B7B7B7" />
<TextBlock Text="183XXXXXXXX" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="80 5 0 0 ">
<TextBlock Text="邮箱 "
Foreground="#B7B7B7" />
<TextBlock Text="vaemc520@qq.com" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="80 5 0 0 ">
<TextBlock Text="职业 "
Foreground="#B7B7B7" />
<TextBlock Text="计算机/互联网/通信" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="80 5 0 0 ">
<TextBlock Text="空间 "
Foreground="#B7B7B7" />
<TextBlock Text="Go to hell! 的空间" />
</StackPanel>
</StackPanel>
</Grid>

6. 最终效果

 
最终效果

欢迎Star https://github.com/vaemc/WpfTimQQ

7. 总结

接触到了WPF以后感觉用WinForm托控件真的好LOW,并且用WPF可以轻松的设计出好看的界面,以前经常写安卓也发现这俩玩意布局竟如此的雷同,然后就慢慢的过度到了WPF。
下一节将会以此项目为基础来讲诉WPF MVVM框架的实现,欢迎关注~

作者:vaemc
链接:https://www.jianshu.com/p/d105e40a90d4
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

WPF系列教程——(一)仿TIM QQ界面 - 简书的更多相关文章

  1. WPF系列教程——(二)使用Prism实现MVVM设计模式 - 简书

    原文:WPF系列教程--(二)使用Prism实现MVVM设计模式 - 简书 本文假设你已经知道MVVM设计模式是什么,所以直接进入正题,今天我们就用Prism来实现WPF的MVVM设计模式,百度上关于 ...

  2. 【全网最全的博客美化系列教程】02.添加QQ交谈链接

    全网最全的博客美化系列教程相关文章目录 [全网最全的博客美化系列教程]01.添加Github项目链接 [全网最全的博客美化系列教程]02.添加QQ交谈链接 [全网最全的博客美化系列教程]03.给博客添 ...

  3. WPF系列教程——(三)使用Win10 Edge浏览器内核 - 简书

    原文:WPF系列教程--(三)使用Win10 Edge浏览器内核 - 简书 在需要显示一些 H5网站的时候自带的WebBrowser总是显示不了,WebBrowser使用的是IE内核,许多H5新特性都 ...

  4. Vue3.0网页版聊天|Vue3.x+ElementPlus仿微信/QQ界面|vue3聊天实例

    一.项目简介 基于vue3.x+vuex+vue-router+element-plus+v3layer+v3scroll等技术构建的仿微信web桌面端聊天实战项目Vue3-Webchat.基本上实现 ...

  5. cocos2d-x游戏开发系列教程-坦克大战游戏启动界面的编写

    用前面介绍的方法,创建一个cocos2d-x项目,可以看到新项目内容如下图:

  6. 【全网最全的博客美化系列教程】08.自定义地址栏Logo

    全网最全的博客美化系列教程相关文章目录 [全网最全的博客美化系列教程]01.添加Github项目链接 [全网最全的博客美化系列教程]02.添加QQ交谈链接 [全网最全的博客美化系列教程]03.给博客添 ...

  7. 【全网最全的博客美化系列教程】01.添加Github项目链接

    全网最全的博客美化系列教程相关文章目录 [全网最全的博客美化系列教程]01.添加Github项目链接 [全网最全的博客美化系列教程]02.添加QQ交谈链接 [全网最全的博客美化系列教程]03.给博客添 ...

  8. WPF入门教程系列二十三——DataGrid示例(三)

    DataGrid的选择模式 默认情况下,DataGrid 的选择模式为“全行选择”,并且可以同时选择多行(如下图所示),我们可以通过SelectionMode 和SelectionUnit 属性来修改 ...

  9. WPF入门教程系列三——Application介绍(续)

    接上文WPF入门教程系列二——Application介绍,我们继续来学习Application 三.WPF应用程序的关闭 WPF应用程序的关闭只有在应用程序的 Shutdown 方法被调用时,应用程序 ...

随机推荐

  1. android libs库中的armeabi-v7a,armeabi和x86

    以下内容转载于:http://blog.csdn.net/liumou111/article/details/52949156 1.区别: 这三者都表示的是CPU类型,早期的Android系统几乎只支 ...

  2. 【起航计划 015】2015 起航计划 Android APIDemo的魔鬼步伐 14 App->Activity->Translucent Blur 模糊背景

    这个例子和Translucent不同的一点是Blur,也就是显示在当前Activit背后的其它Activity以模糊方式显示. 这是通过window对象Flag来设置的. // Have the sy ...

  3. 算法练习-Palindrome Number

    判断回文整数 来源 https://leetcode.com/problems/palindrome-number/ 要求 判断一个整数是不是回文数,尽量减少内存暂用. 思路 可能的情况: 负数的应当 ...

  4. iOS获取/删除url中的参数

    1.获取URL中的某个参数: - (NSString *)getParameter:(NSString *)parameter urlStr:(NSString *)url { NSError *er ...

  5. MySQL数据库实验二:单表查询

    实验二   单表查询 一.实验目的 理解SELECT语句的操作和基本使用方法. 二.实验环境 是MS SQL SERVER 2005的中文客户端. 三.实验示例 1.查询全体学生的姓名.学号.所在系. ...

  6. 228. Summary Ranges (everyday promlems) broken problems

    Given a sorted integer array without duplicates, return the summary of its ranges. Example 1: Input: ...

  7. log4net 简单配置

    <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigu ...

  8. ZOJ - 2112 Dynamic Rankings(BIT套主席树)

    纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了... 终于用BIT套函数式线段树了过了,120ms就是快,此题主要是卡内存. 假设离散后有ns个不同的值,递归层数是l ...

  9. ADO.NET之一:连接层

    ADO.NET大部分由System.Data.dll核心程序集来表示. ADO.NET类库有三种完全不听的方式来实现数据访问:连接式.断开式和通过Entity框架.连接式就是会一直占用网络资源,断开式 ...

  10. 用dockers实现mysql主从同步

    首先要先看看当前的mysql的版本是什么,可以通过下面命令查看 mysql --version 最好是安装在docker中的mysql和你宿主机器中的mysql版本一致. 我的是mysql5.7.22 ...