自定义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并没有直接的用户交互, ...
随机推荐
- Software: MPEG-7 Feature Extraction Library
Software MPEG-7 Feature Extraction Library : This library is adapted from MPEG-7 XM Reference Softwa ...
- Java基础类库
1 main方法 运行java程序的参数: 下面详细讲解main 方法为什么采用这个方法签名 1.public 修饰符:Java类由jvm调用,为了让jvm可以自由调用这个main()方 ...
- hql 关联查询
HQL 带的连接语句只能是实体与 该实体的属性 进行连接 其意义就是为了优化(通过延迟加载查询关联的属性)需要进行配置 from A left join A.B where (b.flag is nu ...
- 【Python】django表单与提交
参考:http://djangobook.py3k.cn/2.0/chapter07/ 本文的内容应属于django的表单模块,没有涉及到的后端request对象的处理方法可以单独深入学习表单. UR ...
- 消息推送之APNS
利用APNS进行消息推送 原理 APNS 是Apple Push Notification Service(Apple Push服务器)的缩写,是苹果的服务器. APNS推送可以分为三个阶段: 第一阶 ...
- Windows 2003 FastCgi安装环境
Windows 2003 IIS+PHP5.4.3 安装教程 一.准备相关组件 安装前,先安装IIS. 1.安装FastCgi for IIS6 Fastcgi官方网址是:http://www.iis ...
- Show Users Assigned to a Specific Role
In a previous post I showed you how to know what Roles are assigned to a specific user. But here is ...
- javascript的变量,传值和传址,参数之间关系
先把收获晾一下: 1.javascrip变量包含两种类型的值,一种为引用类型的值,一种是基本类型的值.引用类型包括:Array,Object,Function(可以这么理解,非基本类型的都是引用类型) ...
- LevelDB系列之SSTable(Sorted Strings Table)文件
SSTable是Bigtable中至关重要的一块,对于LevelDb来说也是如此,对LevelDb的SSTable实现细节的了解也有助于了解Bigtable中一些实现细节. 本节内容主要讲述SSTab ...
- JS中cookie的基本使用
cookie是本身是HTML中ducument中的一个属性,可以用来保存一些简单的数据信息,比如用户名.密码等,提高一些网站的用户体验度.下面就来简单的说说cookie,它有下面几个特性: 1.有过期 ...