自定义Drawable_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > 自定义Drawable

自定义Drawable

 2015/5/5 15:04:24  wx0123  程序员俱乐部  我要评论(0)
  • 摘要:本文由伯乐在线-treesouth翻译,toolate校稿。未经许可,禁止转载!英文出处:ryanharter.com。欢迎加入翻译小组。我们看过一些博客文章,讲述了为什么要适时地使用自定义的view,以及它们是如何帮你正确地封装应用代码的。却少有人讨论这类思考如何转变为我们的app中与view无关的其它部分。在我开发的应用程序Fragment里,在一些地方我使用自定义的Drawable封装我的逻辑代码,就像使用自定义view一样。代码放在Gist!用例在Fragment中
  • 标签:自定义
本文由class="Apple-converted-space"> 伯乐在线 - treesouth 翻译,toolate 校稿。未经许可,禁止转载! 英文出处:ryanharter.com。欢迎加入翻译小组。

我们看过一些博客文章,讲述了为什么要适时地使用自定义的view,以及它们是如何帮你正确地封装应用代码的。却少有人讨论这类思考如何转变为我们的app中与view无关的其它部分。

在我开发的应用程序Fragment里,在一些地方我使用自定义的Drawable封装我的逻辑代码,就像使用自定义view一样。代码放在Gist!

用例

在Fragment中,我们使用了水平方向的滑动条作为一些地方的可选的视图区域。这就意味着中央的图标是被选择的图标,每一项都能够以平滑移动的方式移进移出。由此,我们认为最好展现出一个优雅的过渡效果。

example

然而这并非完全必要。我认为这是一个效果,它使得运动更为流畅,并给应用增加了些许品味。我本可以设置多个图像view并单独呈现,但是这却是自定义drawable的最佳使用场景。

自定义Drawable

在Android中,Drawable实际上是很接近于View。它们有相似的方法获取布局的边距和边界,并且有可以被覆写的draw方法。在我的例子里,我需要在选中和未选中这两个基于值的drawable中实现平移效果。

在我们的例子中,我们简单地创建出来包含了其他Drawables(含方向)的Drawable的子类。

1 2 3 4 5 6 7 8 9 monospace !important; font-size: 12px !important; font-style: normal !important; font-weight: bold !important; vertical-align: baseline !important; float: none !important; position: static !important; min-height: inherit !important; box-sizing: content-box !important;">public class RevealDrawable extends Drawable {   public RevealDrawable(Drawable unselected, Drawable selected, int orientation) {     this(null, null);       mUnselectedDrawable = unselected;     mSelectedDrawable = selected;     mOrientation = orientation;   } }

接下来,我们需要做的就是设定一个值,用来标明drawable是选中的一栏。恰好Drawable有一个内置函数可以做到这一点,即setLevel(int)。

一个Drawable的级别是从0到10000的整数值,这仅仅允许Drawable根据一个值来定义它的视图。在我们的例子中,我们可以简单地设定5000作为选中状态,0表示左侧完全未选中,10000表示右侧完全未选中。

我们要做的就是重写draw(Canvas canvas)方法,根据当前level值裁剪canvas,从而绘制合适的drawable。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 @Override public void draw(Canvas canvas) {     // If level == 10000 || level == 0, just draw the unselected image   int level = getLevel();   if (level == 10000 || level == 0) {     mRevealState.mUnselectedDrawable.draw(canvas);   }     // If level == 5000 just draw the selected image   else if (level == 5000) {     mRevealState.mSelectedDrawable.draw(canvas);   }     // Else, draw the transitional version   else {     final Rect r = mTmpRect;     final Rect bounds = getBounds();       { // Draw the unselected portion       float value = (level / 5000f) - 1f;       int w = bounds.width();       if ((mRevealState.mOrientation & HORIZONTAL) != 0) {         w = (int) (w * Math.abs(value));       }       int h = bounds.height();       if ((mRevealState.mOrientation & VERTICAL) != 0) {         h = (int) (h * Math.abs(value));       }       int gravity = value < 0 ? Gravity.LEFT : Gravity.RIGHT;       Gravity.apply(gravity, w, h, bounds, r);         if (w > 0 && h > 0) {         canvas.save();         canvas.clipRect(r);         mRevealState.mUnselectedDrawable.draw(canvas);         canvas.restore();       }     }       { // Draw the selected portion       float value = (level / 5000f) - 1f;       int w = bounds.width();       if ((mRevealState.mOrientation & HORIZONTAL) != 0) {         w -= (int) (w * Math.abs(value));       }       int h = bounds.height();       if ((mRevealState.mOrientation & VERTICAL) != 0) {         h -= (int) (h * Math.abs(value));       }       int gravity = value < 0 ? Gravity.RIGHT : Gravity.LEFT;       Gravity.apply(gravity, w, h, bounds, r);         if (w > 0 && h > 0) {         canvas.save();         canvas.clipRect(r);         mRevealState.mSelectedDrawable.draw(canvas);         canvas.restore();       }     }   } }

就这样,我们仅仅设置了基于滚动位置的水平方向的图标,这事就搞定了。

1 2 3 4 5 6 float offset = getOffestForPosition(recyclerView, position); if (Math.abs(offset) <= 1f) {   holder.image.setImageLevel((int) (offset * 5000) + 5000); } else {   holder.image.setImageLevel(0); }

如果你想看到这份自定义Drawable的源代码,你可以在Github的这里查看。

发表评论
用户名: 匿名