Android圆角Tag控件的另类实现
一般的圆角标签控件都是用xml设置shape做实现。可是假设我们想要做一个更加强大通用的的圆角控件,不须要使用者去关心圆角,仅仅设置背景就能够了。
应该怎么实现呢?这个就须要把背景先设置成图片,然后再把这个图片处理成圆角的,最后再设置成背景。基本思路例如以下代码:
Bitmap bitmap = ((BitmapDrawable)getBackground()).getBitmap();
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
Matrix matrix = new Matrix();
bitmapShader.setLocalMatrix(matrix);
// 设置缩放
float scale = Math.max(getWidth() * 1.0f / bmp.getWidth(), getHeight() * 1.0f / bmp.getHeight());
mBitmapPaint.setShader(bitmapShader);
Canvas canvas = new Canvas(bitmap); if (mRadius > 0) {
canvas.drawRoundRect(mDrawableRect, mRadius, mRadius, mBitmapPaint);
} else {
canvas.drawRect(mDrawableRect, mBitmapPaint);
}
setBackground(new BitmapDrawable(bitmap));
上面的代码把背景图取出来后,用着色器画圆角(假设背景色是color,须要做一次ColorDrawable转Bitmap的转换)。这样就行强制实现一个圆角背景的TextView了。你也可以使用Xfermode来做,网上文章非常多。不做赘述了。
如今问题来了,假设我背景是ShapDrawable(xml:shape)或者设置的StateListDrawable(selector)呢?这就没办法了,ShapeDrawable还可以做自己定义,可是StateListDrawable开放的可以自己定义的接口非常少,全然没办法。
此外,假设我们须要设置drawableLeft或者drawableRight。也会掩盖住背景。圆角也就没了。
假设也对这些compound drawable也设置圆角。并且圆角的半径还不能和主空间的半径一样。否则会因为宽高不同。画出来的圆角也会不一样。
这个方法太复杂。
放弃!
有没有什么简单的办法呢?我们能够用Xfermode来对画板的底图做文章。
这里就要说到Android(预计其它OS也是差点儿相同)控件的实现方式了。
我们在显示屏看到的全部东西。事实上都是一块内存,放在一块叫做framebuffer的内存缓冲区里面。这块Buffer以像素点为单位,用一定的色彩规则,给我们排列出了各种看到的屏幕上的东西。Android通过一个叫Surface的系统来管理这一块FrameBuffer,所谓的控件,事实上就是依照一定的规则,告诉Surface系统怎么画我这一块区域。这样就行给我们具体的画出我们想要看到的画面了。关于细节,东西太多,以后再慢慢说。
继续说到实现圆角控件的问题来。
Android里面全部的控件,都给我们提供了一个叫onDraw()的方法,參数为Canvas。Canvas就是画布的意思,我们在这块布上面画的东西。就是空间的长相了。
这种方法会在View.draw()里面调用下来,告诉系统怎么画这个控件。比方TextView里面的onDraw就基本是一些写字。设置颜色,字体的操作,ImageView就是用Drawable来画canvas的操作。
Android提供了各种各样的方法,方便我们对这块Canvas进行操作。我们想要实现圆角,是不是能够对这块Canvas做点手脚呢?我们能够Xfermode来画一个椭圆形 的Bitmap在原图上面,然后仅仅保留他们相交的这一部分。去掉不相交的部分,圆角控件不就大功告成了?关于Xfermode,有一经典的图深动形象的说明了使用方法:
我们想要做的就例如以下图:
生成掩盖图的代码例如以下:
private Bitmap generateMaskBitmap() {
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas bitmapCanvas = new Canvas(bitmap);
RectF r = new RectF(0, 0, getWidth(), getHeight());
Rect rect = new Rect(0, 0, getWidth(), getHeight());
Paint bitmapPaint = new Paint();
bitmapPaint.setAlpha(0);
bitmapPaint.setColor(Color.TRANSPARENT);
bitmapCanvas.drawRect(rect, bitmapPaint);
bitmapPaint.reset();
bitmapPaint.setStyle(Paint.Style.FILL);
bitmapPaint.setAntiAlias(true);
bitmapPaint.setColor(Color.WHITE);
bitmapCanvas.drawRoundRect(r, mRadius, mRadius, bitmapPaint);
return bitmap;
}
onDraw代码例如以下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mRadius > 0) {
Bitmap bitmap = generateMaskBitmap();
Paint bitmapPaint = new Paint();
bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
canvas.drawBitmap(bitmap, 0f, 0f, bitmapPaint);
bitmap.recycle();
}
}
可是这样并不OK啊。用这个控件却是这样:
<com.example.widget.TagTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ff0000"
android:text="哎哟不错"
app:border_radius="5dp"
/>
为什么会这样呢?圆角是有了,可是为嘛周围是是黑色啊。感觉代码是没问题的呀,后来去网上搜了下。XferMode在开启了硬件加速的情况下有一些局限性(http://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported),预计这个问题也是局限性之中的一个。于是在本widget关闭了硬件加速,又一次build后,发现还是没有变化。我就有点晕了,为嘛不是其它颜色。偏偏是黑色啊,并且我的maskBitmap也是设置的白色呀。
解释仅仅能为一个了:我的Background没有设置alpha值,没有不论什么的透明度,导致删除的颜色变为了无颜色状态。我来设置一个带有透明度的背景色试试:
<com.example.widget.TagTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#feff0000"
android:text="哎哟不错"
app:border_radius="5dp"
/>
能够了耶。这样,以后不管这个控件做了什么,画出来周围肯定是圆角的。
总结
我有尝试事先画一个透明的Color在控件上,可是仍然无论用。详细原因还不知道。还没来得及深入的去看。假设有哥们知道。最好还是分享一下原因。
Android圆角Tag控件的另类实现的更多相关文章
- Android 中常见控件的介绍和使用
1 TextView文本框 1.1 TextView类的结构 TextView 是用于显示字符串的组件,对于用户来说就是屏幕中一块用于显示文本的区域.TextView类的层次关系如下: java.la ...
- 【风马一族_Android】第4章Android常用基本控件
第4章Android常用基本控件 控件是Android用户界面中的一个个组成元素,在介绍它们之前,读者必须了解所有控件的父类View(视图),它好比一个盛放控件的容器. 4.1View类概述 对于一个 ...
- [Android] Android 卡片式控件CardView的优雅使用
[Android] Android 卡片式控件CardView的优雅使用 CardView是在安卓5.0提出的卡片式控件 其具体用法如下: 1.在app/build.gradle 文件中添加 comp ...
- android 开发 ScrollView 控件的一些api描述与自定义ScrollView接口回调方法
1.正常使用ScrollView控件的一些api详解. package com.example.lenovo.mydemoapp.scrollViewDemo; import android.supp ...
- android中倒计时控件CountDownTimer分析
android中倒计时控件CountDownTimer分析 1 示例代码 new CountDownTimer(10000, 1000) { public void onTick(long milli ...
- Android中ListView控件的使用
Android中ListView控件的使用 ListView展示数据的原理 在Android中,其实ListView就相当于web中的jsp,Adapter是适配器,它就相当于web中的Servlet ...
- 五、Android学习第四天补充——Android的常用控件(转)
(转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 五.Android学习第四天补充——Android的常用控件 熟悉常用的A ...
- 注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式
注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式 这个坑,必须要注意呀, 比如在用ListView的时候,如果在List_ ...
- Android其它新控件 (转)
原文出处:http://blog.csdn.net/lavor_zl/article/details/51312715 Android其它新控件是指非Android大版本更新时提出的新控件,也非谷歌I ...
随机推荐
- Solr.NET快速入门(七)【覆盖默认映射器,NHibernate集成】
覆盖默认映射器 默认情况下,SolrNet使用属性映射Solr字段. 但是,您可能需要使用另一个映射程序. 替换默认映射器取决于您如何设置库: 内置容器 如果使用默认的内置容器,可以在调用Startu ...
- Codeforces Round #453
Visiting a Friend Solution Coloring a Tree 自顶向下 Solution Hashing Trees 连续2层节点数都超过1时能异构 Solution GCD ...
- TensorFlow-mnist
训练代码: from __future__ import absolute_import from __future__ import division from __future__ import ...
- mysql简单语句
创建名为user的数据库: create database user; 显示所有数据库: show databases; 选择名为user的数据库: use user; 显示所有表: show tab ...
- Boost多线程-替换MFC线程
Mfc的多线程看起来简单,可以把线程直接压入向量,由系统类似进行调配,其实在内存的处理问题上留下了漏洞.在新线程里面载入大量流,会导致内存泄露. 方便之处:直接使用结构体传入函数参数,供 ...
- mvc关于pots请求 哪个函数 出现bug研究
这样能请求home下的updateA函数 这样能请求home下的update函数,不能请求updateA函数
- PhotoZoom控制面板简介说明
PhotoZoom是一款极其简单的图片无损放大工具,简单几步渲染出完美的放大照片,呈现无与伦比的画质效果.即可虽然简单,菜单和面板的功能很少,但却是设计师的必备神器,因为其简单易用性,它的软件菜单命令 ...
- 面试官:为什么mysql不建议执行超过3表以上的多表关联查询?
概述 前段时间在跟其他公司DBA交流时谈到了mysql跟PG之间在多表关联查询上的一些区别,相比之下mysql只有一种表连接类型:嵌套循环连接(nested-loop),不支持排序-合并连接(sort ...
- 任务调度开源框架Quartz概述
任务调度开源框架Quartz 几乎每个项目中都用到了自动任务处理功能.所以在任务调度的功能很常用,但是一个好的任务调度程序是一个颇具挑战性的工作.最近用到Quartz这个框架,感觉很好,所以进行学习. ...
- Elasticsearch学习(一)————简单命令
Elasticsearch一.简介**Elasticsearch 是一个分布式的搜索和分析引擎,可以用于全文检索.结构化检索和分析,并能将这三者结合起来.Elasticsearch 基于 Lucene ...