自定义Drawable
我们看过一些博客文章,讲述了为什么要适时地使用自定义的view,以及它们是如何帮你正确地封装应用代码的。却少有人讨论这类思考如何转变为我们的app中与view无关的其它部分。
在我开发的应用程序Fragment里,在一些地方我使用自定义的Drawable封装我的逻辑代码,就像使用自定义view一样。代码放在Gist!
用例
在Fragment中,我们使用了水平方向的滑动条作为一些地方的可选的视图区域。这就意味着中央的图标是被选择的图标,每一项都能够以平滑移动的方式移进移出。由此,我们认为最好展现出一个优雅的过渡效果。

然而这并非完全必要。我认为这是一个效果,它使得运动更为流畅,并给应用增加了些许品味。我本可以设置多个图像view并单独呈现,但是这却是自定义drawable的最佳使用场景。
自定义Drawable
在Android中,Drawable实际上是很接近于View。它们有相似的方法获取布局的边距和边界,并且有可以被覆写的draw方法。在我的例子里,我需要在选中和未选中这两个基于值的drawable中实现平移效果。
在我们的例子中,我们简单地创建出来包含了其他Drawables(含方向)的Drawable的子类。
|
1
2
3
4
5
6
7
8
9
|
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
|
@Overridepublic 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的这里查看。
自定义Drawable的更多相关文章
- [转]自定义Drawable实现灵动的红鲤鱼动画(下篇)
小鱼儿 上篇文章自定义Drawable实现灵动的红鲤鱼动画(上篇)我们绘制了可以摆动身体的小鱼,本篇就分享一下如何让小鱼游到手指点击的位置.用到的主要技术如下: 1).三阶贝塞尔曲线 2).Pat ...
- [转]自定义Drawable实现灵动的红鲤鱼动画(上篇)
此篇中的小鱼动画是模仿国外一个大牛做的flash动画,第一眼就爱上它了,简约灵动又不失美学,于是抽空试着尝试了一下,如下是我用Android实现的效果图: 小鱼儿 由于整个绘制分析过程比较繁琐所以 ...
- Android APK开发 Drawable文件夹下的自定义Drawable文件
版本:2018/2/11 Drawable的分类 自定义Drawable SVG矢量图 个人总结的知识点外,部分知识点选自<Android开发艺术探索>-第六章 Drawable 1.Dr ...
- Android 自定义Drawable
1.使用BitmapShader实现图片圆角 public class CornerDrawable extends Drawable { private Paint mPaint; private ...
- Android自定义drawable(Shape)详解
在Android开发过程中,经常需要改变控件的默认样式, 那么通常会使用多个图片来解决.不过这种方式可能需要多个图片,比如一个按钮,需要点击时的式样图片,默认的式样图片. 这样就容易使apk变大. 那 ...
- Android 使用自定义Drawable 设置圆角矩形或者圆形图片
转自 Android Drawable 那些不为人知的高效用法 本文出自:[张鸿洋的博客] http://blog.csdn.net/lmj623565791/article/details/437 ...
- Drawable与Bitmap 自定义
Drawable简介 Drawable是Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF.PNG.JPG,当然也支持BMP.相比于View,我们并不需要去考虑如何measure. ...
- Android Drawable 那些不为人知的高效用法
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43752383,本文出自:[张鸿洋的博客] 1.概述 Drawable在我们平时的 ...
- Android自定义View之倒计时Countdown实现
先看一下效果: 在点击OK键之后,开始倒计时. 实现步骤 1.新建Android工程"CountdownView" 2.自定义Drawable 自定义View并没有直接的用户交互, ...
随机推荐
- 学习总结 html图片热点,网页划区,拼接,表单
表单: action="负责处理的 <form id="" name="" method="post/get"服务端&quo ...
- ViewPager撤消左右滑动切换功能
ViewPager取消左右滑动切换功能 最近做项目要求某种情况下ViewPager不能滑动,那么我们只需要重写这个方法就可以禁止ViewPager滑动 IndexViewPager.java: imp ...
- php odbc连接 查询显示不完整问题
首先php.ini里里面mssql查询的默认配置是4096 1.找到[MSSQL] ; Valid range 0 - 2147483647. Default = 4096.mssql.textlim ...
- WIN32 DLL中使用MFC
最近用WIN32 DLL,为了方便要用到MFC的一些库,又不想转工程,就网上找了很多方法,发现没有详细的介绍,有的也行不通,现在成功在WIN32 DLL中使用了MFC,记录一下以防以后用到忘记 一.修 ...
- tech
流式计算框架storm.spark.genfire.esper(CEP)
- js 获取当前日期时间 格式为 yyyy-mm-dd hh:MM:ss
------------------------------------------------------------------------------------ js 获取当前日期时间 格式为 ...
- Glassfish数据源配置详解
本文环境: Win2003 + myeclipse6.01 + sqlserver2000(sp4) 1. 安装glassfish——启动,在管理控制台下配置如下 首先配置连接池——大家把sqlser ...
- JS常用的设计模式(7)—— 外观模式
外观模式(门面模式),是一种相对简单而又无处不在的模式.外观模式提供一个高层接口,这个接口使得客户端或子系统更加方便调用.用一段再简单不过的代码来表示 var getName = function() ...
- Oracle多线程并行使用、关联与指定索引执行
nologging AS SELECT /*+parallel(4) leading(s a) use_hash(A) index(s IDX_CS_SERVICE_RECORD_MD2_04) */ ...
- Java druid
1.ConnectionFactory (添加引用:druid-1.0.1.jar) package nankang.test; import java.sql.Connection; import ...