Android图片添加水印

在项目开发进行中,要求给商品图片添加水印。有什么好办法呢?搜索网上的大致有两种方案

  • ImageView视图加载出现之后在进行加载
  • 在布局中写布局文件实现

以上两种方案都不能很好的满足项目的需要,所以就考虑到重写ImageView,在onDraw方法中做事情

  • WatermarkImageView继承ImageView
public class WatermarkImageView extends AppCompatImageView {

   private Bitmap mWatemarkBitmap;
   private RectF srcRect;
   private PorterDuffXfermode mXfermode;

   public WatermarkImageView(Context context) {
        this(context, null);
    }

    public WatermarkImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WatermarkImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        init();
    }

    /**
     * 默认资源初始化
     */
    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
        mWatemarkBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_prologo);
    }
}
  • 重写onDraw()方法
   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 创建水印图层
        int i = canvas.saveLayer(srcRect, mPaint, Canvas.ALL_SAVE_FLAG);
        // 设置模式,为直接覆盖到原图
        mPaint.setXfermode(mXfermode);
        // 绘制水印到当前图层
        canvas.drawBitmap(mWatemarkBitmap, null, srcRect, mPaint);
        // 清除模式
        mPaint.setXfermode(null);
        // 将如上画的层覆盖到原有层级上
        canvas.restoreToCount(i);
    }
  • 设置属性
    1.arrays.xml文件内容

     
        
        
        
        
        
        
        
        
        
            
            
            
            
            
        
    
    

    2.代码获取属性

      /**
     * 从xml文件中获取属性
     *
     * @param attrs attrs
     */
    private void initAttribute(AttributeSet attrs) {
        TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.WatermarkImageView);
        int N = typedArray.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.WatermarkImageView_watermark_src:
                    // Bitmap bitmap = ((BitmapDrawable) typedArray.getDrawable(attr)).getBitmap();
                    int resourceId = typedArray.getResourceId(attr, R.drawable.ic_prologo);
                    mWatemarkBitmap = BitmapFactory.decodeResource(getResources(), resourceId);
                    break;
                case R.styleable.WatermarkImageView_watermark_visible:
                    mIsWatermark = typedArray.getBoolean(R.styleable.WatermarkImageView_watermark_visible, false);
                    break;
                case R.styleable.WatermarkImageView_watermark_width:
                    mWatermarkWidth = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_width, -1);
                    Log.d("mWatermarkWidth" + mWatermarkWidth);
                    break;
                case R.styleable.WatermarkImageView_watermark_height:
                    mWatermarkHeight = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_height, -1);
                    Log.d("mWatermarkHeight" + mWatermarkHeight);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_top:
                    mWatermarkPaddingTop = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_top, -1);
                    Log.d("mWatermarkPaddingTop" + mWatermarkPaddingTop);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_right:
                    mWatermarkPaddingRight = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_right, -1);
                    Log.d("mWatermarkPaddingRight" + mWatermarkPaddingRight);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_left:
                    mWatermarkPaddingLeft = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_left, -1);
                    Log.d("mWatermarkPaddingLeft" + mWatermarkPaddingLeft);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_bottom:
                    mWatermarkPaddingBottom = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_bottom, -1);
                    Log.d("mWatermarkPaddingBottom" + mWatermarkPaddingBottom);
                    break;
                case R.styleable.WatermarkImageView_watermark_location:
                    mCurrentLocate = typedArray.getInteger(R.styleable.WatermarkImageView_watermark_location, mCurrentLocate);
                    Log.d("mCurrentLocate" + mCurrentLocate);
                    break;
                default:
                    break;
            }
        }
        typedArray.recycle();
    }
    
  • 完整代码

package com.pbs.xpjx.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.support.annotation.IntDef;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

import com.bsh.sdk.utils.DisplayUtil;
import com.pbs.xpjx.R;
import com.pbs.xpjx.utils.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 图片添加水印(目前该view只支持添加图片,后续如需要添加文字可以继续添加)
 * Created by timmy.tan on 2017/11/23.
 */

public class WatermarkImageView extends AppCompatImageView {

    public static final int LOCATE_LEFT_TO_TOP = 0; // 左上
    public static final int LOCATE_RIGHT_TO_TOP = 1; // 右上
    public static final int LOCATE_LEFT_TO_BOTTOM = 2; // 左下
    public static final int LOCATE_RIGHT_TO_BOTTOM = 3; // 右下
    public static final int LOCATE_CENTER = 4; // 居中


    @IntDef({LOCATE_LEFT_TO_TOP, LOCATE_RIGHT_TO_TOP, LOCATE_LEFT_TO_BOTTOM, LOCATE_RIGHT_TO_BOTTOM, LOCATE_CENTER})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Locate {
    }

    @Locate
    int mCurrentLocate = LOCATE_RIGHT_TO_TOP;

    private Context mContext;
    private Paint mPaint;
    private int mScale = 5; // 设置水印图与原图的比例
    private Bitmap mWatemarkBitmap;
    private RectF srcRect;
    private PorterDuffXfermode mXfermode;
    private boolean mIsWatermark = false;
    private int mWatermarkWidth = -1; // 水印宽度
    private int mWatermarkHeight = -1; // 水印高度
    private int mWatermarkPaddingTop;
    private int mWatermarkPaddingRight;
    private int mWatermarkPaddingLeft;
    private int mWatermarkPaddingBottom;


    public WatermarkImageView(Context context) {
        this(context, null);
    }

    public WatermarkImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WatermarkImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        init();
        initAttribute(attrs);
    }

    /**
     * 默认资源初始化
     */
    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
        mWatemarkBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_prologo);
    }

    /**
     * 从xml文件中获取属性
     *
     * @param attrs attrs
     */
    private void initAttribute(AttributeSet attrs) {
        TypedArray typedArray = getResources().obtainAttributes(attrs, R.styleable.WatermarkImageView);
        int N = typedArray.getIndexCount();
        for (int i = 0; i < N; i++) {
            int attr = typedArray.getIndex(i);
            switch (attr) {
                case R.styleable.WatermarkImageView_watermark_src:
                    // Bitmap bitmap = ((BitmapDrawable) typedArray.getDrawable(attr)).getBitmap();
                    int resourceId = typedArray.getResourceId(attr, R.drawable.ic_prologo);
                    mWatemarkBitmap = BitmapFactory.decodeResource(getResources(), resourceId);
                    break;
                case R.styleable.WatermarkImageView_watermark_visible:
                    mIsWatermark = typedArray.getBoolean(R.styleable.WatermarkImageView_watermark_visible, false);
                    break;
                case R.styleable.WatermarkImageView_watermark_width:
                    mWatermarkWidth = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_width, -1);
                    Log.d("mWatermarkWidth" + mWatermarkWidth);
                    break;
                case R.styleable.WatermarkImageView_watermark_height:
                    mWatermarkHeight = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_height, -1);
                    Log.d("mWatermarkHeight" + mWatermarkHeight);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_top:
                    mWatermarkPaddingTop = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_top, -1);
                    Log.d("mWatermarkPaddingTop" + mWatermarkPaddingTop);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_right:
                    mWatermarkPaddingRight = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_right, -1);
                    Log.d("mWatermarkPaddingRight" + mWatermarkPaddingRight);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_left:
                    mWatermarkPaddingLeft = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_left, -1);
                    Log.d("mWatermarkPaddingLeft" + mWatermarkPaddingLeft);
                    break;
                case R.styleable.WatermarkImageView_watermark_padding_bottom:
                    mWatermarkPaddingBottom = typedArray.getLayoutDimension(R.styleable.WatermarkImageView_watermark_padding_bottom, -1);
                    Log.d("mWatermarkPaddingBottom" + mWatermarkPaddingBottom);
                    break;
                case R.styleable.WatermarkImageView_watermark_location:
                    mCurrentLocate = typedArray.getInteger(R.styleable.WatermarkImageView_watermark_location, mCurrentLocate);
                    Log.d("mCurrentLocate" + mCurrentLocate);
                    break;
                default:
                    break;
            }
        }
        typedArray.recycle();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // 不设置宽高默认按比例计算
        if (mWatermarkWidth < 0) {
            mWatermarkWidth = w / mScale;
        }
        if (mWatermarkHeight < 0) {
            mWatermarkHeight = h / mScale;
        }
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;

        switch (mCurrentLocate) {
            case LOCATE_LEFT_TO_TOP:
                // 左上
                left = mWatermarkPaddingLeft;
                top = mWatermarkPaddingTop;
                right = mWatermarkWidth + mWatermarkPaddingLeft;
                bottom = mWatermarkHeight + mWatermarkPaddingTop;
                break;

            case LOCATE_RIGHT_TO_TOP:
                // 右上
                left = w - mWatermarkWidth - mWatermarkPaddingRight;
                top = mWatermarkPaddingTop;
                right = left + mWatermarkWidth;
                bottom = top + mWatermarkHeight;
                break;

            case LOCATE_LEFT_TO_BOTTOM:
                // 左下
                left = mWatermarkPaddingLeft;
                top = h - mWatermarkPaddingBottom - mWatermarkHeight;
                right = left + mWatermarkWidth;
                bottom = h - mWatermarkPaddingBottom;
                break;

            case LOCATE_RIGHT_TO_BOTTOM:
                // 右下
                left = w - mWatermarkPaddingRight - mWatermarkWidth;
                top = h - mWatermarkPaddingBottom - mWatermarkHeight;
                right = w - mWatermarkPaddingRight;
                bottom = h - mWatermarkPaddingBottom;
                break;

            case LOCATE_CENTER:
                // 居中
                int parentHalfW = w >> 1;
                int watermarkHalfW = mWatermarkWidth >> 1;
                int parentHalfH = h >> 1;
                int watermarkHalfH = mWatermarkHeight >> 1;

                left = parentHalfW - watermarkHalfW;
                top = parentHalfH - watermarkHalfH;
                right = parentHalfW + watermarkHalfW;
                bottom = parentHalfH + watermarkHalfH;
                break;
            default:
                break;
        }
        srcRect = new RectF(left, top, right, bottom);


    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (false) {
            drawWatermark(canvas);
        }
    }

    /**
     * 画水印
     *
     * @param canvas canvas
     */
    private void drawWatermark(Canvas canvas) {
        // 创建水印图层
        int i = canvas.saveLayer(srcRect, mPaint, Canvas.ALL_SAVE_FLAG);
        // 设置模式,为直接覆盖到原图
        mPaint.setXfermode(mXfermode);
        // 绘制水印到当前图层
        canvas.drawBitmap(mWatemarkBitmap, null, srcRect, mPaint);
        // 清除模式
        mPaint.setXfermode(null);
        // 将如上画的层覆盖到原有层级上
        canvas.restoreToCount(i);
    }


    /**
     * 是否显示水印
     *
     * @param b true 显示 false 不显示
     */
    public void showWatermark(boolean b) {
        this.mIsWatermark = b;
        // 视图重绘,执行onDraw()方法
        invalidate();
    }

    public Bitmap getWatemarkBitmap() {
        return mWatemarkBitmap;
    }

    public void setWatemarkBitmap(Bitmap mWatemarkBitmap) {
        this.mWatemarkBitmap = mWatemarkBitmap;
        invalidate();
    }

    public int getWatermarkWidth() {
        return mWatermarkWidth;
    }

    public void setWatermarkWidth(int mWatermarkWidth) {
        this.mWatermarkWidth = mWatermarkWidth;
        invalidate();
    }

    public int getWatermarkHeight() {
        return mWatermarkHeight;
    }

    public void setWatermarkHeight(int mWatermarkHeight) {
        this.mWatermarkHeight = mWatermarkHeight;
        invalidate();
    }

    public int getCurrentLocate() {
        return mCurrentLocate;
    }

    public void setCurrentLocate(@Locate int mCurrentLocate) {
        this.mCurrentLocate = mCurrentLocate;
        invalidate();
    }
}

  • 使用指南
  

你可能感兴趣的:(Android图片添加水印)