zoukankan      html  css  js  c++  java
  • c#,使用WPF实现iPhone的短信框效果

    先来看看iPhone的短信界面,就当是麻豆了 ^-^。

    这么简洁美丽又大方的界面也就苹果想的出来。

    刚看到这个界面,口水就止不住啊。

    擦干口水,赶紧模仿。

    最初做法:

      基于UserControl,自己做一个用户控件,内含TextBolck可以实现多行显示文本,

    使用Path和Geometry将带有小尾巴的图形画出来,然后再画上光照效果,就大功

    告成了。

      虽然效果能做出来,但是细细想来,还是有不妥。

      问题就在于,自己作的这个控件,只能显示文字,为了要显示图片,还得写一堆代码,

    太过死板,为什么就不能利用WPF的框架或特点,让这个控件变的灵活一些,只要些

    绘图效果和控制布局的效果就OK了,至于内部包含的是文字还是图片,就交给WPF去

    完成好了。

      基于此,立马想到为TextBlock控件写个Template,但稍稍一定神发现,用Template

    完成复杂图形的绘制有些虚无缥缈,结果放弃。

      在老大的点化之下,采用Decorater。乍看之下,有点摸不着北,细细看来,发现,

    Border就是从此类继承而来,说白了就是包含一个子元素的容器,自定义的Decorater

    负责绘制图形背景,显示的内容就交给子元素去完成。

      为什么不用Border而用它,道理就是用它就足够了,干净。

      (当然了,容器还有Panel,ContentControl,在这里用Decorater就够了)。

      主要就是用到基类的方法:

        MeasureOverride:通过测量子元素来计算需要的空间的大小。

        ArrangeOverride:排列子元素的显示位置。

        OnRender:自绘函数,带小尾巴的图形绘制就在这里了,等价于OnPaint。

    最终的效果:

     

    实现。

    自定义IDecorator类:

    public class iDecorator : Decorator {
            public iDecorator() {
                this.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
            }
    
            public bool Direction {
                get { return (bool)GetValue(DirectionProperty); }
                set { SetValue(DirectionProperty, value); }
            }
    
            protected override Size MeasureOverride(Size constraint) {
                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;
                    if (result.Height < 35) {
                        result.Height = 35;
                        padding.Top = padding.Bottom = (result.Height - Child.DesiredSize.Height) / 2;
                    }
    
                }
                return result;
            }
    
            protected override Size ArrangeOverride(Size arrangeSize) {
                if (Child != null) {
                    Child.Arrange(new Rect(new Point(padding.Left, padding.Top),
                        Child.DesiredSize));
                }
                return arrangeSize;
            }
    
            protected override void OnRender(DrawingContext dc) {
                if (Child != null) {
    
                    Geometry cg = null;
    
                    Brush brush = null;
    
                    Pen pen = new Pen();
    
                    pen.Brush = new SolidColorBrush(Colors.Black);
                    pen.Thickness = 1;
    
                    if (Direction) {
                        //生成小尾巴在右侧的图形和底色
                        cg = CreateGeometryTailAtRight();
    
                        brush = CreateBrushTailAtRight();
                    }
                    else {
                        //生成小尾巴在左侧的图形和底色
                        cg = CreateGeometryTailAtLeft();
    
                        brush = CreateBrushTailAtLeft();
                    }
    
                    dc.DrawGeometry(brush, pen, cg);
    
                    //绘制光照效果
                    GradientStopCollection gscLight = new GradientStopCollection();
                    gscLight.Add(new GradientStop(Color.FromArgb(0xDA, 0xFF, 0xFF, 0xFF), 0));
                    gscLight.Add(new GradientStop(Color.FromArgb(0x68, 0xFF, 0xEF, 0xFF), 1));
                    Brush lightBrush = new LinearGradientBrush(gscLight, new Point(0, 0), new Point(0, 1));
                    dc.DrawRoundedRectangle(lightBrush, null, new Rect(22, 1, this.ActualWidth - 45, 20), 10, 10);
    
            }

    //省略部分代码。。。
    public static void OnDirectionPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { var self = d as iDecorator; self.HorizontalAlignment = (bool)e.NewValue ? HorizontalAlignment.Right : HorizontalAlignment.Left; } private Thickness padding = new Thickness(25, 6, 25, 6); public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register("Direction", typeof(bool), typeof(iDecorator), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender, OnDirectionPropertyChangedCallback)); }

    调用处:

    短信框的小尾巴在右侧:

                    <local:iDecorator HorizontalAlignment="Right" Direction="True">
                        <TextBlock MaxWidth="200" Foreground="Black" TextWrapping="Wrap">前两天去哪儿了,听说去北京了???</TextBlock>
                    </local:iDecorator>

    短信框的小尾巴在左侧:

    就是把Direction(方向)设成False即可。

                    <local:iDecorator HorizontalAlignment="Right" Direction="False">
                        <TextBlock MaxWidth="200" Foreground="Black" TextWrapping="Wrap">前两天去哪儿了,听说去北京了???</TextBlock>
                    </local:iDecorator>

    调用是不是很方便,把它当成容器用就行了。

    大功告成!

    代码:http://download.csdn.net/download/kongxh_1981/9161495

  • 相关阅读:
    如何导入文件夹在项目中
    KVC的学习
    ScrollView学习01
    KVO与KVC整理资料
    KVO监听者
    进程与线程
    解决SQL 2008数据库日志文件过大导致占满整个分区的问题:清理数据库日志文件
    SharePoint开发中发现的SharePoint本身的一些问题
    从十个方面提升SharePoint网站性能
    解决SharePoint2010文档库中新建文档不是保存到文档库而是保存到本地电脑的问题
  • 原文地址:https://www.cnblogs.com/kongxianghai/p/2446125.html
Copyright © 2011-2022 走看看