码迷,mamicode.com
首页 > 移动开发 > 详细

然并卵, Xamarin Android 仿制个性动画菜单

时间:2015-08-07 00:13:59      阅读:217      评论:0      收藏:0      [点我收藏+]

标签:

唱衰 .NET / Xamarin 的, 看完图示就可以关掉了.

不为证明什么, 仅为示例, 不做实际用途, 所以然并卵.

照例,上图

技术分享

 

上代码: https://github.com/gruan01/Xamarin-Example/tree/master/DiscMenu

 

此示例 防照: http://blog.csdn.net/lmj623565791/article/details/43131133

不过没有按照他样那做, 因为那也是然并卵. 谁会把 App 做的如此花梢? 

 

 

本示例主要 实践 SurfaceView , 及 Animator 的用法.

如图所示, 中心那个滚动的圆形头像, 是用 Surface 做的, 虽然用 Animation 一样可以做.

弹出的子项是用 Animator 做的.

 

SurfaceView

SurfaceView 不受 UI 线程干扰, 所以它的 OnDraw 方法实现了也是白实现.  

它需要自带一个独立的线程去更新视图内容.

要绘制, 当然需要一个 Canvas , 它可以这样获取:

1                 using (var canvas = this.Holder.LockCanvas()) {
2                     if (canvas != null) {
3                         this.DrawBitmap(canvas, this.Center);
4                         this.DrawRing(canvas);
5                     }
6                     this.Holder.UnlockCanvasAndPost(canvas);
7                 }

 

不过, 你最好加上 try..catch..

当 Resume 的时候, 这里会出点小异常.

 

LockCanvas() 方法返回绘制所需的 Canvas,

UnlockCanvasAndPost() 是把绘制的内容提交, 并释放 canvas.

 

另外, 必须实现 ISurfaceHolderCallback 接口, 并注册

1 public class CenterView : SurfaceView, ISurfaceHolderCallback, IRunnable {
2     ...
3     public CenterView(Context ctx, Bitmap center, int radius) : base(ctx) {
4         ...
5         this.Holder.AddCallback(this);

 

 

在 ISurfaceHolderCallback  的方法 SurfaceCreated 中开启自己的线程, 无限循环的进行绘制

1         public void SurfaceCreated(ISurfaceHolder holder) {
2             this.IsRunning = true;
3             this.Thread = new Java.Lang.Thread(this);
4             this.Thread.Start();
5         }

 

 

在 VS 的 Android 模拟器下, 如果不设置:

this.Holder.SetFormat(Format.Transparent);

 

这个 SurfaceView 的内容就不会显示, 但是一切都是正常执行的, 在 Android SDK 自带的模拟器下就没有问题.

网易新闻客户端 中的 视频, 在 VS 的模拟器上也不显示画面, 我猜也是因为这个问题.

 

Surface 就这么简单,  余下的, 就靠自己脑洞大开了.

 

 

 

Canvas 相关技巧

1, 旋转

如上图所示的那个不断旋转的头像, 其实是先旋转 canvas , 然后在绘制

        private void DrawBitmap(Canvas c, Bitmap bmp) {
            var sc = c.Save();

            this.Degree = this.Degree % 360 + DEGREE_STEP;
            //要先旋转,后画图才有效果
            c.Rotate(this.Degree, c.Width / 2, c.Height / 2);

            ...
            c.DrawBitmap(bmp, null, rect, paint);

 

顺序反了是不会有效果的.

 

2, 镂空

如图所示的和头像反着转的那个绿色线条, 其实是对大的圆形做角度渐变, 然后用小一点的圆形进行镂空, 当然画布也是旋转了的.

 1             //用两个圆 Path 构造一个 圆环显示区域, 即挖空内圆
 2             var pInner = new Path();
 3             pInner.AddCircle(cx, cy, this.BitmapRadius + SPACE / 2, Path.Direction.Cw);
 4             var pOut = new Path();
 5             pOut.AddCircle(cx, cy, this.Radius, Path.Direction.Cw);
 6 
 7             c.ClipPath(pOut);
 8             c.ClipPath(pInner, Region.Op.Difference);
 9 
10             //var color = new Color((int)(DateTime.Now.Ticks % 0xFFFFFFFF));
11             //c.DrawColor(color);
12 
13             //用角度渐变填充外圆的范围
14             var g = new SweepGradient(cx, cy, Color.Green, Color.Transparent);
15             var paint = new Paint();
16             paint.SetShader(g);
17             c.DrawCircle(cx, cy, this.Radius, paint);

 

c 是 canvas,  

c.ClipPath(pOut),  即限制 canvas 只绘制为 pOut 这个 path 的闭合区域.

c.ClipPath(pInner, Region.Op.Difference)   即把 pInner 的 闭合区域 从 上一句 的 绘制区域 中排除.

顺序不要搞反, 反了没有效果.

 

3, 补充: 正反两个方向

一个方向转动没意思, 两个方向是怎么做的呢? 很简单,  绘制头向的时候按正角度(x) , 绘制头向外面那一圈是用的 -x

 

 

Animator

SurfaceView 不好做交互控制, 所以弹出子项的动画是用 Animator 做的.

Android 的 Animation 分为好多种, 我不了解, 现学现卖而已.

这里主要是实现了 子项 位置/大小 的变化, 所以 我用了 ObjectAnimator

var aniX = ObjectAnimator.OfFloat(c, "X", xs);
var aniY = ObjectAnimator.OfFloat(c, "Y", ys);
var aniSX = ObjectAnimator.OfFloat(c, "ScaleX", ss);
var aniSY = ObjectAnimator.OfFloat(c, "ScaleY", ss);

 

其中的 c 即是子项 view, 

X, Y, ScaleX, ScaleY 你可以理解为 .NET 的反射, 它要用反射去更新这些属性的值.

 

展开与收回

是两个向反的过程, 即把起始值与结束值互换一下就可以了

float[] xs = new float[] { cx - hw, l };
float[] ys = new float[] { cy - hy, t };
float[] ss = new float[] { 0.1f, 1 };
if (!expand) {
    Array.Reverse(xs);
    Array.Reverse(ys);
    Array.Reverse(ss);
}

 

一开始, 我想把这些 Animator 保存起来, 当收起的时候, 就把各个 animator.Reverse() 一下, 这样就可以得到向反的动画. 但是总是收回不到中心点, 所以, 我放弃了这种想法.

 

跳蛋模式

我自己给它取的名字, 其实是 Interpolator

set.SetInterpolator(new Android.Views.Animations.BounceInterpolator());

 

试了几个 Interpolator , 就这个跳蛋模式能在展开的时候, 把最右边的的那个子项展开到指定的点上.

 

圆形排列

我数学早还给老师了, 这里用的到三角函数, 勾股定理 都是百度来的, 所以表问我.

 

-----------------------

完, 谢谢观赏, 请点..........

然并卵, Xamarin Android 仿制个性动画菜单

标签:

原文地址:http://www.cnblogs.com/xling/p/4709477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!