关于android图片混合示例
来源:互联网 发布:mac将图标放在桌面 编辑:程序博客网 时间:2024/05/17 05:08
先看第一个效果图:
前景的背景是一个图片,后景的背景是淡蓝色(即左上角小圈里的颜色),左上角的圆圈还有一个边框
看图片效果其实就是需要在一个图片的某个地方透明显示一个圆形区域(附加一个边框);用图片的混合实现起来其实很简单,直接上代码:
/** * 在一个原图上绘制一个指定位置和大小的空心透明(可附带边框)的圆 * * @param src 原图 * @param w 新的宽度 * @param h 新的高度 * @param cx 圆的中心坐标x * @param cy 圆的中心坐标y * @param radius 圆的半径 * @param padding 圆的边框大小 * @param color 圆的边框颜色 * @return */ public Bitmap processCricle(Bitmap src, int w, int h, int cx, int cy, int radius, int padding, int color) { //首先你可能需要缩放原图 int sw = src.getWidth(); int sh = src.getHeight(); Matrix matrix = new Matrix(); matrix.setScale(1.0f * w / sw, 1.0f * h / sh); Bitmap scaleBmp = Bitmap.createBitmap(src, 0, 0, sw, sh, matrix, true); //开始 Bitmap newBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(newBmp); Paint paint = new Paint(); paint.setAntiAlias(true); //画空心圆 paint.setStyle(Paint.Style.FILL); canvas.drawCircle(cx + padding, cy + padding, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); canvas.drawBitmap(scaleBmp, 0, 0, paint); //画边框 if (padding > 0) { paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(padding); paint.setColor(color); canvas.drawCircle(cx + padding, cy + padding, radius, paint); } scaleBmp.recycle(); return newBmp; }
代码里面有注释,我就不过多叙述了,主要使用了二种PorterDuffXfermode模式,当然代码的开头对原图做了一个缩放操作,你可以忽略。下面来看第二种效果图:
整个图片需要显示一个立体效果,效果图的主要部分可以是任何图片(资源/本地/网络)
首先图片里的文字直接PASS
背景遮罩:实现上图中背景遮罩的部分采用了层叠形式,看下图就明白了:
我们知道ImageView有 背景 和 前景 的概念,所以直接将背景遮罩设为它的背景图片就好:
<com.xxxx.view.CardView android:id="@+id/pic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:background="@drawable/fl_bg" android:scaleType="matrix" />看代码,上面的CardView是一个自定义的ImageView,它的背景为fl_bg,就是上面的那个背景遮罩效果图。下面是自定义view的源码:
public class CardView extends ImageView { private static final String TAG = "CardView" public int width, height;//图片实际的宽高 boolean flag = false;//标志位,很重要 public static int WIDTH;//默认的宽,取屏幕的宽度,实际值可随意指定 public CardView (Context context, AttributeSet attrs) { this(context, attrs, 0); } public CardView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); if (WIDTH == 0) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); //view_padding这里作者的图宽度是占满屏幕,所有采用的默认值是屏幕的宽度 float offset = context.getResources().getDimension(R.dimen.view_padding); WIDTH = (int) (metrics.widthPixels - offset * 2); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取view的宽度,这里作者的图宽度是占满屏幕,所以采用了MOST,你可以指定一个具体的宽和高 if (width == 0) { width = MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.AT_MOST); } init(); setMeasuredDimension(width, height); } //初始化宽高 void init() { if (width <= 0) { width = getMeasuredWidth(); } if (height <= 0) { height = Util.getFitHeight(width); } }
//为了解决部分机型获取width失败的崩溃问题,你在获取CardView的宽高时,务必使用下面二个方式 public int getWidthEx() { if (width <= 0 || height <= 0) { width = WIDTH; height = Util.getFitHeight(width); } return width; } public int getHeightEx() { if (width <= 0 || height <= 0) { width = WIDTH; height = Util.getFitHeight(width); } return height; }
/**
* when flag is false: * setImageBitmap -> * setCardBitmap -> * setImageBitmap -> * super.setImageBitmap -> * setImageDrawable -> * super.setImageDrawable * when flag is true: * setImageBitmap->super.setImageBitmap ->setImageDrawable ->super.setImageDrawable * * @param bm */ @Override public void setImageBitmap(Bitmap bm) { if (!flag) { flag = true; Util.setCardBitmap(this, bm); } else { super.setImageBitmap(bm); flag = false; } } @Override public void setImageDrawable(Drawable drawable) { if (!flag) { flag = true; Util.setCardBitmap(this, drawable); } else { super.setImageDrawable(drawable); flag = false; } }上面配合注释,读起来应该很简单,这里要特殊说明一下,如果你像采用指定大小的宽高,请确保宽高和背景遮罩图的宽高比例一致,其中二个Util方法的实现如下,最后我会专门解释下上面的flag:
/* 688比302.59 背景遮罩图的宽高 圆中心与顶部的距离与原图高度比 50比302.59 圆半径:9像素 */ public final static float FB_ASPECT_1 = 302.59f / 688; public final static float FB_ASPECT_2 = 50 / 302.59f; public final static int FB_RADIUS = 9; //根据宽高比以及实际宽度获取高 public static int getFitHeight(int width) { return (int) (width * FB_ASPECT_1); } //设置前景图,drawableToBitmap转换我就不写了 public static void setCardBitmap(CardView view, Drawable source) { setCardBitmap(view, drawableToBitmap(source)); } //设置前景图 public static void setCardBitmap(CardView view, Bitmap source) { final float density = getResources().getDisplayMetrics().density;//偏移值,实际上,前景图和背景图并不是完全重叠了,前景图的宽高比背景图稍微小一点,如果完全一样,你就看不到阴影了 final int of = (int) (6 * density); //注意这里调用的方法名称final int width = view.getWidthEx() - of; final int height = view.getHeightEx() - of;//圆的半径以及距离顶部的偏移 final int radius = (int) (FB_RADIUS * density); final int offset = (int) (height * FB_ASPECT_2); //first scale the source float w = source.getWidth(); float h = source.getHeight(); Matrix matrix = new Matrix(); matrix.postScale(width / w, height / h); //长和宽放大缩小的比例 Log.i(TAG, width + "," + height + "|" + w + "," + h); final Bitmap scale = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true); final Paint paint = new Paint(); paint.setAntiAlias(true); final Bitmap target = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); /** * 产生一个同样大小的画布 */ Canvas canvas = new Canvas(target); /** * 首先绘制圆形 */ canvas.drawCircle(0, offset, radius, paint); canvas.drawCircle(width, offset, radius, paint); /** * 使用SRC_OUT */ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); /** * 绘制图片 */ canvas.drawBitmap(scale, 0, 0, paint); //last recycle all unuseful bitmap source.recycle(); scale.recycle(); Bitmap round = createRoundConerImage(target, width, height, radius >> 1); view.setImageBitmap(round); } /** * 根据原图添加圆角 * * @param source * @return */ public static Bitmap createRoundConerImage(Bitmap source, int width, int height, int radius) { final Paint paint = new Paint(); paint.setAntiAlias(true); Bitmap target = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(target); RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight()); canvas.drawRoundRect(rect, radius, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(source, 0, 0, paint); source.recycle(); return target; }根据注释应该不难理解,实际上你可以把他放在一个文件内。
最后我说下flag的问题,我的原图是从网络获取的,好吧有一个开源的universalimageloader,那就用上吧,但这个库的displayImage会直接把图片缩放后设置到imageview中,该如何拦截了?这就是上面flag以及重载ImageView二个设置前景图的原因了。看ImageView源码,可以发现它的 setImageBitmap 实际调用的是 setImageDrawable 方法,据此,结合CardView的那个简单注释,我想你画个调用图,应该就可以理解了
0 0
- 关于android图片混合示例
- 关于SwipeRefreshLayout和RecyclerView混合使用的代码示例
- android textview混合显示图片和文字
- 图片混合
- Android 图片合成Xfermode示例
- Android缩放图片和旋转图片示例
- 关于ANDROID示例程序(BITMAPFUN)——高效加载图片的坑爹地方
- 关于android示例程序(bitmapfun)——高效加载图片的缺陷
- 关于android示例程序(bitmapfun)——高效加载图片的坑爹地方
- 关于android示例程序(bitmapfun)——高效加载图片的坑爹地方
- Android关于图片压缩
- android 关于图片压缩
- Android关于图片压缩
- Android开发系列:怎么混合显示图片和文本
- Android开发系列八:怎么混合显示图片和文本
- Android TextView中有图片有文字混合排列
- Android TextView使用HTML处理图片文字混合显示
- Android获取网络图片应用示例
- 【转载】Android样式的开发:shape篇
- LightOJ-1008 Fibsieve`s Fantabulous Birthday
- 【php中的curl】php中curl的详细解说
- Linux安装mysql——源码安装
- 将自己的代码上传到maven中央库
- 关于android图片混合示例
- 【Android】 JNI入门 - NDK从入门到精通
- c语言总结
- Android 动画-----补间动画
- 蓝桥杯算法提高 -- 周期字串
- KVM max memory allocation
- jQuery dataTables 的使用
- 修改StatusBar颜色
- 联想企业云docker开发实践