您的位置:首页 > 移动开发 > IOS开发

Xamarin.iOS 波浪效果

2016-12-21 11:49 387 查看
以前Android写过一个demo,是波浪效果,应该是仿照百度外卖的那个头像效果。突然想拿Xamarin来试试,利用我的脑洞终于给弄出来了,不知道方法是不是合理。先贴出来展示一下吧.



实际效果是波浪在动,头像以及文字也在上下动,给人一种效果就是头像和文字是漂在波浪上面的。

下面来说一下实现吧:

首先将看见的这个view分成三个view,分别实现。第一个view就是波浪view,即如下图


就是类似一个正弦曲线的这么一个效果。

第二个就是头像加文字的view,把她单独出来做一个view目的就是可以单独控制它的动画来配合波浪的动画。

下面首先来看看波浪view的画法:新建一个View继承UIView。通过Draw方法来画线,想要实现波浪效果让它动起来,最少要画两个屏幕长度的波浪,这个大家应该能理解吧。

还有一点注意的就是我没有找到直接画正弦的方法,最后是用贝塞尔曲线拼接而成的。

看下代码:

using System;
using System.Drawing;
using CoreGraphics;
using UIKit;

namespace RuilaiGrow.iOS
{
/// <summary>
/// 波浪View
/// by ge
/// </summary>
public class WaveView : UIView
{

//正线曲线,顶部,中线,底部Y轴高度
private nfloat _waveTop = 50f;
private nfloat _waveHalfHei = 65f;
private nfloat _waveBottom = 80f;

public WaveView()
{
this.Frame = new RectangleF(0, 0, (float)(UIScreen.MainScreen.Bounds.Width * 2), (float)_waveBottom);
this.BackgroundColor = UIColor.White;
}

//划线
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);

//本View上半部分红色背景矩形
CGContext contextBac = UIGraphics.GetCurrentContext();
contextBac.SetFillColor(MvxTouchColor.DeepRed.CGColor);
contextBac.AddRect(new RectangleF(0, 0, (float)(UIScreen.MainScreen.Bounds.Width * 2), (float)_waveHalfHei));
contextBac.FillPath();
//屏幕的宽度
nfloat viewWid = UIScreen.MainScreen.Bounds.Width;

//利用贝塞尔曲线完成正弦波浪曲线
//分成两次画出正弦曲线
for (int i = 0; i < 2; i++)
{
nfloat startX = i * viewWid;

//左半边弧
CGContext contextLeft = UIGraphics.GetCurrentContext();
contextLeft.SetLineWidth(1f);
contextLeft.SetStrokeColor(MvxTouchColor.DeepRed.CGColor);
contextLeft.MoveTo(startX, _waveHalfHei);
contextLeft.AddCurveToPoint(startX, _waveHalfHei,
(startX + viewWid / 4), _waveTop,
(startX + viewWid / 2), _waveHalfHei);
contextLeft.SetFillColor(MvxTouchColor.White.CGColor);
contextLeft.DrawPath(CGPathDrawingMode.EOFill);

//右半边弧
CGContext contextRight = UIGraphics.GetCurrentContext();
contextRight.SetLineWidth(1f);
contextRight.SetStrokeColor(MvxTouchColor.DeepRed.CGColor);
contextRight.MoveTo((startX + viewWid / 2), _waveHalfHei);
contextRight.AddCurveToPoint((startX + viewWid / 2),
_waveHalfHei, (startX + (System.nfloat)(viewWid * 0.75)),
_waveBottom, startX + viewWid, _waveHalfHei);
contextRight.SetFillColor(MvxTouchColor.AlphaDeepRed.CGColor);
contextRight.DrawPath(CGPathDrawingMode.EOFill);
}
}
}
}


上面我将整个类都贴出来,因为没啥难度,不过有一点要注意的,就是在波浪下凹处仔细看会有一点透明白色的区域,这个区域我是将右半边弧度用了一个透明颜色填充了。大家可以自己换。

头像和文字的view我就不占用这里的地方了,没什么要注意的。

下面直接贴出来整体的View的类:

注:

1.代码中最下面部分就是波浪view与头像view的动画。波浪view还好说,就是一个循环左移的动画,头像的动画的轨迹分析一下:一个正弦函数移动,应该是先向下移动一个驼峰距离,在向上移动两个驼峰距离,在向下移动一个驼峰距离。这是一个完整的周期,下一个动画循环这个周期即可。

2.代码中使用了一种控件间的约束方式,大家可以换成自己的,如果需要的话可以私聊我。

3.动画属性我设置的是匀速的,即UIViewAnimationOptions.CurveLinear这里,相关属性大家查ios原生的就可以查到。

4.本人水平有限,可能用的都是特别简单的东西来实现这个功能,可能多走了些弯路或者有更好的实现方式,希望大家可以多多提建议,共同进步。

using System;
using System.Drawing;
using CoreGraphics;
using RuilaiGrow.iOS.Common;
using UIKit;

namespace RuilaiGrow.iOS
{
/// <summary>
/// 里程碑模块主页顶部头像View
/// by ge
/// </summary>
public class UserHeaderView : UIView
{

private nfloat _waveBottom = 80f;
private nfloat _waveTopHei = 7f;

//波浪条
private WaveView _waveView = null;
public WaveView WaveView {
get {
if (_waveView == null) {
_waveView = new WaveView();
}
return _waveView;
}
}

//头像,名字,年龄布局
private UIView _headerView = null;
public UIView HeaderView {
get {
if (_headerView == null) {
_headerView = new UIView();
_headerView.AddSubview(HeaderImg);
_headerView.AddSubview(NameText);
_headerView.AddSubview(AgeText);
}
return _headerView;
}
}

//头像
private UIButton _headerImg = null;
public UIButton HeaderImg {
get {
if (_headerImg == null) {
_headerImg = new UIButton();
_headerImg.SetImage(UIImage.FromFile("icon_child_head.png"), UIControlState.Normal);
}
return _headerImg;
}
}

//名字
private UILabel _nameText = null;
public UILabel NameText {
get {
if (_nameText == null) {
_nameText = new UILabel();
_nameText.Text = "小贝";
_nameText.TextAlignment = UITextAlignment.Left;
_nameText.TextColor = MvxTouchColor.White;
_nameText.Font = UIFont.SystemFontOfSize(18f);
return _nameText;
}
return _nameText;
}
}

//月龄
private UILabel _ageText = null;
public UILabel AgeText {
get {
if (_ageText == null)
{
_ageText = new UILabel();
_ageText.Text = "43个月";
_ageText.TextAlignment = UITextAlignment.Left;
_ageText.TextColor = MvxTouchColor.GraySix;
_ageText.Font = UIFont.SystemFontOfSize(13f);
}
return _ageText;
}
}

/// <summary>
/// 构造函数
/// 设定背景色与frame
/// </summary>
public UserHeaderView()
{
this.Frame = new RectangleF(0, 0, (float)UIScreen.MainScreen.Bounds.Width, (float)_waveBottom);
this.BackgroundColor = UIColor.White;
}

//提交view
public override void LayoutSubviews()
{
base.LayoutSubviews();

nfloat textMarTop = 6f;
nfloat marBottom = 6f;

this.AddSubview(WaveView);
this.AddSubview(HeaderView);

//一种aotolayout方式进行view约束
this.ConstrainLayout(() =>
HeaderView.Frame.Bottom == this.Frame.Bottom - marBottom
&& HeaderView.Frame.Width == this.Frame.Width
&& HeaderView.Frame.Height == this.Frame.Height - marBottom
);

HeaderView.ConstrainLayout(() =>
HeaderImg.Frame.Bottom == HeaderView.Frame.Bottom
&& HeaderImg.Frame.GetCenterX() == HeaderView.Frame.GetCenterX()

&& NameText.Frame.Top == HeaderImg.Frame.Top + textMarTop
&& NameText.Frame.Left == HeaderImg.Frame.Right + textMarTop
&& NameText.Frame.Right == HeaderView.Frame.Right

&& AgeText.Frame.Top == NameText.Frame.Bottom
&& AgeText.Frame.Left == HeaderImg.Frame.Right + textMarTop
&& AgeText.Frame.Right == HeaderView.Frame.Right
);

//开启动画
startAnimation(UIScreen.MainScreen.Bounds.Width);
}

/// <summary>
/// 开始波浪动画 动画结束监听中重启本方法
/// </summary>
/// <param name="leftMove">Left move.</param>
public void startAnimation(nfloat leftMove)
{
startHeadAnimation(_waveTopHei, true);
var waveFrame = WaveView.Frame;
waveFrame.X = WaveView.Frame.X - leftMove;
UIView.Animate(12d, 0d, UIViewAnimationOptions.CurveLinear, () => WaveView.Frame = waveFrame,
() =>
{

waveFrame.X = WaveView.Frame.X + leftMove;
WaveView.Frame = waveFrame;

/** 动画完成监听 **/
startAnimation(leftMove);
});
}

/// <summary>
/// 头像初次view动画
/// </summary>
/// <param name="waveTopHei">Wave top hei.</param>
public void startHeadAnimation(nfloat waveTopHei, bool isFirst)
{
var headerFrame = HeaderView.Frame;
headerFrame.Y = HeaderView.Frame.Y + waveTopHei;
UIView.Animate(3d, 0d, UIViewAnimationOptions.CurveLinear, () => HeaderView.Frame = headerFrame,
() =>
{
waveTopHei = waveTopHei * 2;
waveTopHei = -waveTopHei;

if (!isFirst)
return;

/** 动画完成监听 **/
startHeadAnimationAgain(waveTopHei);
});
}

/// <summary>
/// 头像view动画
/// </summary>
/// <param name="waveTopHei">Wave top hei.</param>
public void startHeadAnimationAgain(nfloat waveTopHei)
{
var headerFrame = HeaderView.Frame;
headerFrame.Y = HeaderView.Frame.Y + waveTopHei;
UIView.Animate(6d, 0d, UIViewAnimationOptions.CurveLinear, () => HeaderView.Frame = headerFrame,
() =>
{
waveTopHei = waveTopHei / 2;
waveTopHei = -waveTopHei;

/** 动画完成监听 **/
startHeadAnimation(waveTopHei, false);
});
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息