标签:
唱衰 .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 不受 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 , 然后在绘制
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);
顺序反了是不会有效果的.
如图所示的和头像反着转的那个绿色线条, 其实是对大的圆形做角度渐变, 然后用小一点的圆形进行镂空, 当然画布也是旋转了的.
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 的 闭合区域 从 上一句 的 绘制区域 中排除.
顺序不要搞反, 反了没有效果.
一个方向转动没意思, 两个方向是怎么做的呢? 很简单, 绘制头向的时候按正角度(x) , 绘制头向外面那一圈是用的 -x
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 , 就这个跳蛋模式能在展开的时候, 把最右边的的那个子项展开到指定的点上.
我数学早还给老师了, 这里用的到三角函数, 勾股定理 都是百度来的, 所以表问我.
-----------------------
完, 谢谢观赏, 请点..........
标签:
原文地址:http://www.cnblogs.com/xling/p/4709477.html