摘自:http://site.douban.com/widget/notes/110027/note/88525689/
Android下蒙板效果的实现
2010-09-01 10:59:33
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,也许那些大牛们认为有黑线的才是对的吧 : (
分享到:
相关推荐
在Android开发中,实现蒙板效果常常用于创建各种独特的用户界面元素,比如进度条、按钮或者自定义视图。蒙板效果通常是通过遮罩层来部分隐藏或改变原图像的颜色,以此达到预期的设计效果。本教程将深入讲解如何在...
本篇将详细介绍两种在Android中实现蒙板效果的方法。 1. 不保留标题栏的蒙板效果: 这种效果通常是整个屏幕变暗,除了弹出的窗口保持原样。其原理是通过改变Activity窗口的透明度来达到蒙板的效果。在弹窗显示时,...
总之,Android新手引导蒙层效果的实现并不复杂,主要是通过创建新的布局层、设置背景和添加点击事件来完成。通过理解这些基本步骤,开发者可以根据自己的需求进行扩展和定制,提供更加丰富和引人入胜的用户体验。
本文将深入探讨如何在Android中实现这种“android蒙版(启动引导)”的效果。 首先,我们要了解蒙版的基本概念。蒙版在视觉设计中是指一种覆盖在图像或界面元素上的半透明层,通过改变其透明度来突出或隐藏部分区域...
在Android开发中,遮罩层(Mask Layer)是一种常见的用户界面元素,用于在屏幕上覆盖一层半透明或全透明的颜色,通常用于显示加载提示、弹窗提示或者进行界面过渡效果等。"androdid遮罩层的实现"这个主题,旨在探讨...
在Android中实现教学提示,我们可以利用蒙版(Mask)技术来覆盖一部分界面,突出显示关键操作区域,并配以文字说明。蒙版通常是一个半透明的视图,可以设置为黑色或者某种颜色,以降低背景界面的视觉干扰,使用户的...
先看效果图: 实现代码: BasePopupWindowWithMask.class package com.example.popupwindowwithmask; import android.content.Context; import android.graphics.PixelFormat; import android.graphics.drawable....
为了实现点击FAB后展开item并显示蒙板效果,我们需要使用属性动画。Android的属性动画库允许开发者对View的属性进行平滑过渡,从而实现各种动态效果。我们可以为FAB添加一个点击监听器,在点击事件中启动动画。动画...
优化了UI,综合运用了seletor,handler,thread,adapter,progressbar,sharedpreference,文件读写,坐标换算,onTouch事件监听处理,重写view实现灰色蒙板等效果(没有做多点触屏因为太麻烦了)等,对新人系统运用安卓...
本主题将深入探讨"ImageFilter",一种用于实现图像渲染和滤镜效果的工具或库,它允许开发者对图像进行像素级别的操作,或者添加各种特殊的蒙板效果,为图像增添独特的视觉魅力。 首先,我们要理解什么是图像滤镜。...
2. **添加滤镜效果**:如果你想在拍照时应用特定的滤镜效果,可以编写自定义的JavaScript代码,或者使用现有的JavaScript库(如PixiJS或Fabric.js)处理捕获的图像数据。 3. **用户界面定制**:虽然Cordova本身不...