文档章节

android 蒙版实现

李光正
 李光正
发布于 2015/10/15 14:54
字数 1586
阅读 16
收藏 1
点赞 0
评论 0
Layout结构:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android=" http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    >
    <TextView
        android:id="@+id/left"
        android:text="@string/left"
        android:textSize="18px"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="22px"
        />
    <TextView
        android:id="@+id/middle"
        android:text="@string/middle"
        android:textSize="40px"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        />
<TextView
        android:id="@+id/right"
        android:text="@string/right"
        android:textSize="18px"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="22px"
        />
    <ImageView
        android:id="@+id/mask"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:src="@drawable/mask"
        />
</RelativeLayout>

就是想要下面一个效果:
 

使用的蒙板是:
 


但是问题出现了, 原本期待出现的效果变成了下图:
 

看到了吗?左右两边应该是透明渐变的非常平滑的过渡变成了一条透明一条黑线的巨惨效果,相信你应该能想象到我拿这个效果去给设计师看的时候,他们的头上的黑线不比这少吧…

原因分析
为什么会出现上述的问题呢?那是因为在OPhone 1.5/Android 1.6之后的版本,带Alpha通道,支持透明的PNG24 的渲染是有问题的。在一般的手机上,都只支持到16位色,而这时系统会把PNG24降为PNG8来渲染,这样就出现了上面的惨不忍睹的情况。
所以这时候反而是低版本的手机上是渲染正常的,而这个结果相信是大家都不想看到的。那么有办法解决吗?当然有。

解决方案1 – 抖动(Dithering)

使用抖动,可以解决这个问题吗?
这里的抖动说的不是靠用户本身自己抖动,当频率和那些黑线的频率一致时,蒙板就会变成平滑的渐变…
其实是指使用加入噪点的方式,在过渡的中间进行”抖动 “使渐变更平滑。
设计师/美工可以在他们使用的PhotoShop里面设置加噪点或抖动,还有人特意为这个做了一个滤镜,好人啊。
而程序员有两种方式:
1 直接在代码里面写
ImageView v = (ImageView)findViewById(R.id.mask);
v.getDrawable().setDither(true);

2 使用xml定义drawable
<?xml version="1.0" encoding="UTF-8"?>
<nine-patch
    xmlns:android=" http://schemas.android.com/apk/res/android"
    android:src="@drawable/mask"
    android:dither="true" />
具体可以参见Android Tales的 http://android.amberfog.com/?p=247
于是加了抖动之后的效果:
 


结论: 失败,无论你怎么抖,还是黑线… 是那些大牛的方子不灵吗?No!他们针对的是渐变,不是透明的渐变!抖动的确可以使渐变更平滑,使原来会有间断线或色块的问题解决,但是不会使一个透明渐变的黑线消失。
解决方案2 – 代码生成图像
既然上面的方法失败了,直接用代码生成一个遮罩图呢?咱们可是程序员啊!
下面是生成渐变透明图的代码:
    public static Bitmap createLinear(Context context, int width, int height, int from_color, int to_color){
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        int[] data8888 = new int[width];
        makeRamp(premultiplyColor(from_color), premultiplyColor(to_color), width, data8888);
        bitmap.copyPixelsFromBuffer(makeBuffer(data8888, width));
        return bitmap;
    }

    private static void makeRamp(int from, int to, int n, int[] ramp8888){
        int r = getR32(from) << 23;
        int g = getG32(from) << 23;
        int b = getB32(from) << 23;
        int a = getA32(from) << 23;

        int dr = ((getR32(to) << 23) - r) / (n - 1);
        int dg = ((getG32(to) << 23) - g) / (n - 1);
        int db = ((getB32(to) << 23) - b) / (n - 1);
        int da = ((1 << 23) - a) / (n - 1);
        for (int i = 0; i < n; i++) {
            ramp8888[i] = pack8888(r >> 23, g >> 23, b >> 23, a >> 23);
            r += dr;
            g += dg;
            b += db;
            a += da;
        }
    }
这段不详细解释了,而且也是从Android的ApiDemos里面扒的,基本原理就是一组像素一组像素的设定颜色和Alpha值达到渐变透明的图片。
结论是? 又杯具了。失败的原因应该是这段代码生成的本质还是PNG8,不支持真正的透明。
Ok, 咱们可是程序员,还可以使用渐变的画笔吧:

public static Bitmap createLinearImage(Context context, int width, int height, int color0, int color1, float rate, boolean left) {
        //Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
        //Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
        //Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint();
        Paint paintShader = new Paint();
        LinearGradient shader;
        int w = Math.round(width*rate);
        if (left) {
            paint.setColor(color0);
            canvas.drawRect(0, 0, w, height, paint);
            shader = new LinearGradient(0, 0, width, 0, color0, color1, Shader.TileMode.CLAMP);
            paintShader.setShader(shader);
            canvas.drawRect(w, 0, width, height, paintShader);
        }else{
            shader = new LinearGradient(0, 0, width, 0, color0, color1, Shader.TileMode.CLAMP);
            paintShader.setShader(shader);
            canvas.drawRect(0, 0, width - w, height, paintShader);
            paint.setColor(color1);
            canvas.drawRect(width - w , 0, width, height, paint);
        }
        
        return bitmap;
    }

这段代码是使用了渐变效果的Painter来生成图像,注意我注释掉的那些图片格式,8888其实对应的就是PNG8, 别的是更挫的格式。

结论仍然是不好用。原因应该和上面的一样。

解决方案3 – 去掉透明
这个其实不算一个真正的解决方案,就是不要透明的蒙版,两边直接遮死,不会露出下面的文字。

但是对于一个想做出和IPhone的应用一样精致的程序员是不会接受这样绥靖的方案的。于是最后的解决方案终于到来了。

终极解决方案
Android平台可以使用xml来定义几种图像,其中就包括渐变图。
比如下面的xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android=" http://schemas.android.com/apk/res/android"
>
    <gradient
        android:startColor="#FF000000 "
        android:centerColor="#FF00000"
        android:endColor="#00000000"
        android:shape="rectangle"
        android:centerX="0.2"
        android:angle="0"
    />
</shape>

上面定义的图像翻译成中文就是,这是一张图,它从左到右渐变,开始到20%的地方都是不透明的黑色,从20%到最后开始渐变,变成纯透明的黑色。它的区域的形状是矩形。

所以咱们把这个xml保存到res/drawable目录下,ImageView的src就可以设置成这个文件了。再将原来的layout文件改成一左一右两张蒙版的ImageView, 分别使用上面的drawable和与之成左右镜像的drawble就可以达到最完美的效果了!

就是下面的图所示:

 


结论:使用xml来定义出来的drawble,可以达到完美的渲染。原因是啥呢?这个我也不知道… 估计要去问google的大牛们了。

我推测是前几种的方案系统实现的渲染代码有bug,或者是最后的方案的实现的渲染代码才是bug,也许那些大牛们认为有黑线的才是对的吧 : (

本文转载自:http://blog.csdn.net/liguangzhenghi/article/details/8151570

共有 人打赏支持
李光正
粉丝 5
博文 64
码字总数 0
作品 0
大兴
Android中点击空白区域控件自动隐藏(事件传递机制中的一个小例子)

随着android技术日趋成熟,android应用程序已经由刚开始的单纯效果展示变得越来越艺术话了,各种动画,各种布局层叠,那么由此就产生了一些问题,比如:一个listview的view的item点击时没有反...

xubohui
2013/12/19
0
0
SVG.js - 用于SVG操作和产生动画的一个轻量级js库

SVG.js是一个轻量级的JavaScript库,让您可以轻松地操纵SVG和让SVG产生动画。 SVG.js配有一个整体的方法,如创建,移动,居中,克隆等等。 SVG.js中包含了大量用于定义动画的方法,如移动、缩...

kiwifig
2013/05/26
0
0
Android7.0 分屏下 Activity 与 Fragment 生命周期(一)

小菜前段时间整理了一篇关于我们真的了解 Activity 与 Fragment 的生命周期吗?的小博文,整理了基础版的关于 Activity 与 Fragment 的生命周期。 后来又一次被一个大大神问到在 Android7.0...

阿策神奇
06/11
0
0
安卓滑动隐藏显示菜单功能实现(还有蒙板校果),只显示一半view

好吧.我是标题党.其实我说的显示一半的不是activity. 而是看上去像只显示一半activity. 但真实的是只是操作其中一个view 网上有很多这类的代码. 但怎么都不及自己写的自己理解的深刻. 这文章...

Duke__
2014/03/04
0
0
转: ios与android语音互通方案,类微信

Ios实现amr编解码 Feb 5th, 2012 介绍 学习ios第一个练手功能就是给已有产品加上语音通信功能,能够互通ios与android。这里给出自己的一些心得,希望能给他人一些参考。 资料搜集与参考 类似...

天下杰论
2014/10/30
0
0
今年最新的30个Android库,你了解吗?

Android开发技术越来越成熟,Android开发工具当然也层出叠现。本文就向大家介绍今年最新的深受开发者喜爱的30个Android库。希望对你的Android开发工作能起到助力。 1.MaterialStepperView 它...

Harriet666
2017/10/20
0
0
关于微信的那点帖。。。。。。(各种实例)

照惯例发帖先吐槽一下:最近看到大家发防微信功能特别的多,所以就汇总了一下,看看大家还有什么其他方面的汇总需求,回复我噢,均可满足。。。。。 (ps:有些帖子由于主观、客观还有神马原因...

程序袁_绪龙
2015/04/01
0
0
那些年Android黑科技①:只要活着,就有希望

“黑科技什么的最喜欢了! 对,我们就是要搞事。 来呀。谁怕谁。三年血赚,死刑不亏。(๑´ڡ`๑) ” -- 来自暗世界android工程师 前言: 这个世界上手机有三大系统,苹果、 安卓、 中国安卓 ...

猴亮屏
2017/10/24
0
0
官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?

Kotlin KTX 2月5号的时候,Google 发布了一款 Kotlin 的扩展库,叫 Android KTX,不过现在还处于预览版的状态。它能使 Android 上的 Kotlin 代码更简洁,从而提高开发者的效率和使用体验。 ...

承香墨影
02/07
0
0
应用迁移至 Android P 操作指南

Android P 已经按照既定的计划进入到了 Beta 2 版本,且终版 API 也已经发布。相信大家已经对 Android P 所带来的行为变化以及新功能有了足够的了解。本文将详细说明如何将您的应用迁移至 An...

谷歌开发者
06/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

rabbitmq学习记录(三)

工作队列:一个生产者,多个消费者,生产者直接将消息发送到rabbitmq的队列之中 默认采用的是轮询分配:即不管消费者处理信息的效率,队列给所有消费者轮流发送一条信息,直至消息发送完毕 ...

人觉非常君
19分钟前
0
0
Java 之 反射

反射,剖析 Java类 中的 各个组成部分,映射成 一个个 Java对象,多用于 框架和组件,写出复用性高的通用程序。 测试类代码如下: class Person { private String name; public St...

绝世武神
23分钟前
0
0
华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大

华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大!华为nova3超级慢动作酷玩抖音,没有办法我就是这么强大! 在华为最新发布的nova 3手机上,抖音通过华为himedia SDK集成了60fps、超级...

华为终端开放实验室
29分钟前
0
0
多 SSH Key 实现同一台服务器部署多 Git 仓库

本文以以下需求为背景,介绍详细的做法: 需在同一台服务器同时部署两个不同的 Github 仓库(对 Bitbucket 等 git 服务同样适用) root 用户可在远程登录 SSH 后附上预期的 SSH Key 进行 gi...

yeahlife
31分钟前
0
0
003. es6数值的扩展

一、普通扩展 Number 方法,将字符串、数值转为十进制 : Number('0b111') Number.isFinite() 用来检查一个数值是否为有限的:Number.isFinite(15) Number.isNan() 用来检查一个值是否为NaN N...

秋季长青
45分钟前
0
0
C语言数组和指针的语法糖

对于C语言,我可以这样秀:比如当创建一个数组arr[n]之后,一般我们去遍历数组的时候是for (int i = 0; i < n; i++) { a[i]; }但是我知道下表访问符[]是个语法糖,也就是说a[i]在编译器看来是...

ustbgaofan
53分钟前
0
0
Call to undefined function bcmath()的解决方法

乐意黎的ECS主机环境,Centos7.2 + PHP7 由于使用了bcdiv()函数,运行时总在抛错。 Fatal error: Call to undefined function bcmath() in /usr/loca/apache/htdocs/... on line 4 一查得知:......

dragon_tech
59分钟前
0
0
css优先级

..

architect刘源源
今天
0
0
【转】Twitter的分布式自增ID算法snowflake

结构 snowflake的结构如下(每部分用-分开): 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 第一位为未使用,接下来的41位为毫秒级时间(41位的长度可以...

talen
今天
0
0
hive支持行级修改

Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置。要想支持行级insert、update、delete,需要配置Hive支持事务。 一、Hive具有ACID语义事务的使用场景 1. 流式...

hblt-j
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部