android绘制圆形圆角图片

    xiaoxiao2025-02-09  20

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24555655

    本来想在网上找个圆角的例子看一看,不尽人意啊,基本都是官方的Demo的那张原理图,稍后会贴出。于是自己自定义了个View,实现图片的圆角以及圆形效果。效果图:

    第一个是原图,第二个是圆形效果,第三第四设置了不同的圆角大小。

    准备改变一个博客的风格,首先给大家讲一下原理,让大家明白了,然后再贴代码,不然可以直接看那么长的代码也比较痛苦,核心代码其实就那么几行:

    核心代码分析:

    [java]  view plain  copy   /**       * 根据原图和变长绘制圆形图片       *        * @param source       * @param min       * @return       */       private Bitmap createCircleImage(Bitmap source, int min)       {           final Paint paint = new Paint();           paint.setAntiAlias(true);           Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);           /**           * 产生一个同样大小的画布           */           Canvas canvas = new Canvas(target);           /**           * 首先绘制圆形           */           canvas.drawCircle(min / 2, min / 2, min / 2, paint);           /**           * 使用SRC_IN           */           paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));           /**           * 绘制图片           */           canvas.drawBitmap(source, 00, paint);           return target;       }   其实主要靠:paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));这行代码,为什么呢,我给大家解释下,SRC_IN这种模式,两个绘制的效果叠加后取交集展现后图,怎么说呢,咱们第一个绘制的是个圆形,第二个绘制的是个Bitmap,于是交集为圆形,展现的是BItmap,就实现了圆形图片效果。圆角,其实就是先绘制圆角矩形,是不是很简单,以后别人再说实现圆角,你就把这一行代码给他就行了。

    从Android的示例中,给大家证明一下:

    下面有一张PorterDuff.Mode的16中效果图,咱们的只是其一:

    源码咱们只关心谁先谁后绘制的:

    [java]  view plain  copy   canvas.translate(x, y);                 canvas.drawBitmap(mDstB, 00, paint);                 paint.setXfermode(sModes[i]);                 canvas.drawBitmap(mSrcB, 00, paint);                 paint.setXfermode(null);                 canvas.restoreToCount(sc);   可以看出先绘制的Dst,再绘制的Src,最后的展示是SrcIn那个图:显示的区域是二者交集,展示的是Src(后者)。和咱们前面结论一致。效果16种,大家可以自由组合展示不同的效果。

    好了,原理和核心代码解释完成。下面开始写自定义View。

    1、自定义属性:

    [html]  view plain  copy   <?xml version="1.0" encoding="utf-8"?>   <resources>          <attr name="borderRadius" format="dimension" />       <attr name="type">           <enum name="circle" value="0" />           <enum name="round" value="1" />       </attr>       <attr name="src" format="reference"></attr>          <declare-styleable name="CustomImageView">           <attr name="borderRadius" />           <attr name="type" />           <attr name="src" />       </declare-styleable>      </resources>   2、构造中获取自定义的属性: [java]  view plain  copy   /**   * TYPE_CIRCLE / TYPE_ROUND   */   private int type;   private static final int TYPE_CIRCLE = 0;   private static final int TYPE_ROUND = 1;      /**   * 图片   */   private Bitmap mSrc;      /**   * 圆角的大小   */   private int mRadius;      /**   * 控件的宽度   */   private int mWidth;   /**   * 控件的高度   */   private int mHeight;      public CustomImageView(Context context, AttributeSet attrs)   {       this(context, attrs, 0);   }      public CustomImageView(Context context)   {       this(context, null);   }      /**   * 初始化一些自定义的参数   *    * @param context   * @param attrs   * @param defStyle   */   public CustomImageView(Context context, AttributeSet attrs, int defStyle)   {       super(context, attrs, defStyle);          TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0);          int n = a.getIndexCount();       for (int i = 0; i < n; i++)       {           int attr = a.getIndex(i);           switch (attr)           {           case R.styleable.CustomImageView_src:               mSrc = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));               break;           case R.styleable.CustomImageView_type:               type = a.getInt(attr, 0);// 默认为Circle               break;           case R.styleable.CustomImageView_borderRadius:               mRadius= a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,                       getResources().getDisplayMetrics()));// 默认为10DP               break;           }       }       a.recycle();   }  

    3、onMeasure中获取控件宽高:

    [java]  view plain  copy /**       * 计算控件的高度和宽度       */       @Override       protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)       {           // super.onMeasure(widthMeasureSpec, heightMeasureSpec);           /**           * 设置宽度           */           int specMode = MeasureSpec.getMode(widthMeasureSpec);           int specSize = MeasureSpec.getSize(widthMeasureSpec);              if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate           {               mWidth = specSize;           } else           {               // 由图片决定的宽               int desireByImg = getPaddingLeft() + getPaddingRight()                       + mSrc.getWidth();               if (specMode == MeasureSpec.AT_MOST)// wrap_content               {                   mWidth = Math.min(desireByImg, specSize);               } else                      mWidth = desireByImg;           }              /***           * 设置高度           */              specMode = MeasureSpec.getMode(heightMeasureSpec);           specSize = MeasureSpec.getSize(heightMeasureSpec);           if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate           {               mHeight = specSize;           } else           {               int desire = getPaddingTop() + getPaddingBottom()                       + mSrc.getHeight();                  if (specMode == MeasureSpec.AT_MOST)// wrap_content               {                   mHeight = Math.min(desire, specSize);               } else                   mHeight = desire;           }              setMeasuredDimension(mWidth, mHeight);          }  

    4、根据Type绘制:

    [java]  view plain  copy   /**       * 绘制       */       @Override       protected void onDraw(Canvas canvas)       {              switch (type)           {           // 如果是TYPE_CIRCLE绘制圆形           case TYPE_CIRCLE:                  int min = Math.min(mWidth, mHeight);               /**               * 长度如果不一致,按小的值进行压缩               */               mSrc = Bitmap.createScaledBitmap(mSrc, min, min, false);                  canvas.drawBitmap(createCircleImage(mSrc, min), 00null);               break;           case TYPE_ROUND:               canvas.drawBitmap(createRoundConerImage(mSrc), 00null);               break;              }          }          /**       * 根据原图和变长绘制圆形图片       *        * @param source       * @param min       * @return       */       private Bitmap createCircleImage(Bitmap source, int min)       {           final Paint paint = new Paint();           paint.setAntiAlias(true);           Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);           /**           * 产生一个同样大小的画布           */           Canvas canvas = new Canvas(target);           /**           * 首先绘制圆形           */           canvas.drawCircle(min / 2, min / 2, min / 2, paint);           /**           * 使用SRC_IN,参考上面的说明           */           paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));           /**           * 绘制图片           */           canvas.drawBitmap(source, 00, paint);           return target;       }          /**       * 根据原图添加圆角       *        * @param source       * @return       */       private Bitmap createRoundConerImage(Bitmap source)       {           final Paint paint = new Paint();           paint.setAntiAlias(true);           Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);           Canvas canvas = new Canvas(target);           RectF rect = new RectF(00, source.getWidth(), source.getHeight());           canvas.drawRoundRect(rect, mRadius, mRadius, paint);           paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));           canvas.drawBitmap(source, 00, paint);           return target;       }   好了
    转载请注明原文地址: https://ju.6miu.com/read-1296273.html
    最新回复(0)