在实现扫一扫的功能的时候,我们需要绘制一个中间为透明的扫码框,其余部分为半透明。通常情况下,例如微信或者支付宝的扫码框都是矩形的,如果中间的扫码框是一个矩形,那么布局是很简单的,可是如果扫码框是一个圆角矩形,或者圆形等情况怎么办呢?这篇文章主要是记录绘制一个中间透明带圆角的矩形。
![](https://img.haomeiwen.com/i6449180/d6e7413b56eae783.jpeg)
按照惯例,我们先来看看效果图:
二、按照流程我们就开始来看看代码啦
1、CustomDrawable,支持中间出现透明区域的drawable
packageper.juan.scandome;
importandroid.graphics.Canvas;
importandroid.graphics.ColorFilter;
importandroid.graphics.Paint;
importandroid.graphics.Path;
importandroid.graphics.PorterDuff;
importandroid.graphics.PorterDuffXfermode;
importandroid.graphics.drawable.Drawable;
importandroid.support.annotation.NonNull;
importandroid.support.annotation.Nullable;
/**
*支持中间出现透明区域的drawable
*通过{@link#setSrcPath(Path)}设定透明区域的形状
*Createdbyjuanon2018/07/20.
*/
publicclassCustomDrawableextendsDrawable{
privatePaintsrcPaint;
privatePathsrcPath=newPath();
privateDrawableinnerDrawable;
publicCustomDrawable(DrawableinnerDrawable){
this.innerDrawable=innerDrawable;
srcPath.addRect(100,100,200,200,Path.Direction.CW);
srcPaint=newPaint(Paint.ANTI_ALIAS_FLAG);
srcPaint.setColor(0xffffffff);
}
/**
*设置内部透明的部分
*
*@paramsrcPath
*/
publicvoidsetSrcPath(PathsrcPath){
this.srcPath=srcPath;
}
@Override
publicvoiddraw(@NonNullCanvascanvas){
innerDrawable.setBounds(getBounds());
if(srcPath==null||srcPath.isEmpty()){
innerDrawable.draw(canvas);
}else{
//将绘制操作保存到新的图层,因为图像合成是很昂贵的操作,将用到硬件加速,这里将图像合成的处理放到离屏缓存中进行
intsaveCount=canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),srcPaint,Canvas.ALL_SAVE_FLAG);
//dst绘制目标图
innerDrawable.draw(canvas);
//设置混合模式
srcPaint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.CLEAR));
//src绘制源图
canvas.drawPath(srcPath,srcPaint);
//清除混合模式
srcPaint.setXfermode(null);
//还原画布
canvas.restoreToCount(saveCount);
}
}
@Override
publicvoidsetAlpha(intalpha){
innerDrawable.setAlpha(alpha);
}
@Override
publicvoidsetColorFilter(@NullableColorFiltercolorFilter){
innerDrawable.setColorFilter(colorFilter);
}
@Override
publicintgetOpacity(){
returninnerDrawable.getOpacity();
}
}
(1)主要用到的技术是PorterDuffXfermode的PorterDuff.Mode.XOR模式
(2)核心思想是先正常绘制出整个drawable,然后将指定的区域混合成透明色
2、CustomLayout
packageper.juan.scandome;
importandroid.annotation.SuppressLint;
importandroid.content.Context;
importandroid.graphics.Path;
importandroid.support.annotation.NonNull;
importandroid.support.annotation.Nullable;
importandroid.util.AttributeSet;
importandroid.view.View;
importandroid.widget.FrameLayout;
/**
*根据layout中子View的位置,确定局部透明区域
*Createdbyjuanon2018/07/20.
*/
publicclassCustomLayoutextendsFrameLayout{
privateContextmContext;
privateCustomDrawablebackground;
publicCustomLayout(@NonNullContextcontext){
super(context);
initView(context,null,0);
}
publicCustomLayout(@NonNullContextcontext,@NullableAttributeSetattrs){
super(context,attrs);
this.mContext=context;
initView(context,attrs,0);
}
publicCustomLayout(@NonNullContextcontext,@NullableAttributeSetattrs,intdefStyleAttr){
super(context,attrs,defStyleAttr);
initView(context,attrs,defStyleAttr);
}
@SuppressLint("NewApi")
privatevoidinitView(@NonNullContextcontext,@NullableAttributeSetattrs,intdefStyleAttr){
background=newCustomDrawable(getBackground());
setBackground(background);
}
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){
super.onLayout(changed,left,top,right,bottom);
resetBackgroundHoleArea();
}
@SuppressLint("NewApi")
privatevoidresetBackgroundHoleArea(){
Pathpath=null;
//以子View为范围构造需要透明显示的区域
Viewview=findViewById(R.id.iv_scan);
if(view!=null){
path=newPath();
//矩形透明区域
path.addRoundRect(view.getLeft(),view.getTop(),view.getRight(),view.getBottom(),dp2Px(mContext,10),dp2Px(mContext,10),Path.Direction.CW);
}
if(path!=null){
background.setSrcPath(path);
}
}
publicintdp2Px(Contextcontext,floatdp){
finalfloatscale=context.getResources().getDisplayMetrics().density;
return(int)(dp*scale+0.5f);
}
}
3、然后在XML布局中声明我们的自定义View
android:layout_width="match_parent"
android:id="@+id/frame_layout"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg_image"/>
android:layout_width="match_parent"
android:id="@+id/layout"
android:background="#8c565658"
android:layout_height="match_parent">
android:id="@+id/iv_scan"
android:layout_width="200dp"
android引用块内容center"/>
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值。
网友评论