添加水印在android开发中比较常见,对于那些固定水印直接可以用图片平铺就可以实现了。如果需要根据文字生成动态的水印,可以使用自定义Drawable重写onDraw()方法,来绘制相应的文字。
但如果需要在RecyclerView 上绘制动态水印。你使用上面的方法就会发现,当RecyclerView滑动的时候,水印并不会随着滑动,而是一直固定在哪里。如果需求是需要水印也跟着RecyclerView滑动,那我们应该怎么实现呢?
实现步骤:
1、自定义一个Drawabl用于动态显示水印。
2、用ItemDecoration来绘制水印,并且跟踪滚动位置。
3、由于是重现ItemDecoration的onDraw(),所以该水印的位置在ItemView之下,如果ItemView有背景色将会遮挡住水印
效果图:
单个水印
多个水印
核心代码WatermarkDecoration.java
package eebochina.com.testtechniques.watermark;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.ColorFilter;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.support.annotation.ColorInt;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.support.v7.widget.RecyclerView;import java.util.List;/** * recyclerView 添加水印 */public class WatermarkDecoration extends RecyclerView.ItemDecoration { WatermarkParams mWatermarkParams; WaterMarkDrawable mDrawable; int mScrollY = 0; int mListDrawTextSize = -1; private WatermarkDecoration(WatermarkParams mWatermarkParams) { this.mWatermarkParams = mWatermarkParams; mDrawable = new WaterMarkDrawable(); mListDrawTextSize = mWatermarkParams.mDrawTexts != null ? mWatermarkParams.mDrawTexts.size() : -1; } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); int top = -mScrollY; int right = parent.getWidth() / mWatermarkParams.mColumnNum; int start = Math.abs(mScrollY / mWatermarkParams.mRowHeight); int max = (parent.getHeight() + mScrollY) / mWatermarkParams.mRowHeight + 1; for (int i = start; i < max; i++) { int tempTop = top + (mWatermarkParams.mRowHeight * start); int tempLeft = right / 3; for (int j = 0; j < mWatermarkParams.mColumnNum; j++) { mDrawable.setBounds(tempLeft, top, tempLeft + right, tempTop + mWatermarkParams.mRowHeight); if (mListDrawTextSize == -1) { mDrawable.setDrawTex(mWatermarkParams.mDrawText); } else { mDrawable.setDrawTex(mWatermarkParams.mDrawTexts.get((i * mWatermarkParams.mColumnNum + j) % mListDrawTextSize)); } mDrawable.draw(c); tempLeft += right; } top += mWatermarkParams.mRowHeight; } } //跟踪recyclerView 滚动值 public void setScrollY(int dy) { this.mScrollY += dy; } class WaterMarkDrawable extends Drawable { Paint mPaint; String mTempText; public WaterMarkDrawable() { mPaint = new Paint(); mPaint.setColor(mWatermarkParams.mTextColor); mPaint.setTextSize(mWatermarkParams.mTextSize); mPaint.setAlpha((int) (255 * mWatermarkParams.mAlpha)); mPaint.setAntiAlias(true); mPaint.setTextAlign(Paint.Align.LEFT); } @Override public void draw(@NonNull Canvas canvas) { Rect rect = getBounds(); canvas.save(); canvas.rotate(mWatermarkParams.mDegrees, rect.left, rect.bottom); canvas.drawText(mTempText, rect.left, rect.bottom, mPaint); canvas.restore(); } @Override public void setAlpha(int alpha) { } @Override public void setColorFilter(@Nullable ColorFilter colorFilter) { } @Override public int getOpacity() { return PixelFormat.UNKNOWN; } public void setDrawTex(String mDrawTex) { this.mTempText = mDrawTex; } } public static class Builder { private WatermarkParams mWatermarkParams; //水印背景字符 public Builder(String drawText) { mWatermarkParams = new WatermarkParams(drawText); } //多个水印背景字符 public Builder(ListdrawTexts) { mWatermarkParams = new WatermarkParams(drawTexts); } //文字大小 public Builder setTextSize(int textSize) { mWatermarkParams.mTextSize = textSize; return this; } //文字颜色 public Builder setTextColor(@ColorInt int textColor) { mWatermarkParams.mTextColor = textColor; return this; } //展示多少列 public Builder setColumnNum(int columnNum) { mWatermarkParams.mColumnNum = columnNum; return this; } //行高 public Builder setRowHeight(int rowHeight) { mWatermarkParams.mRowHeight = rowHeight; return this; } //倾斜角度 public Builder setDegrees(int degrees) { mWatermarkParams.mDegrees = degrees; return this; } //透明度 0-1 public Builder setAlpha(float alpha) { mWatermarkParams.mAlpha = alpha; return this; } public WatermarkDecoration builder() { return new WatermarkDecoration(mWatermarkParams); } } static class WatermarkParams { String mDrawText; List mDrawTexts; int mTextColor = Color.parseColor("#ebebeb"); int mTextSize = 40; int mColumnNum = 3; int mRowHeight = 240; int mDegrees = -30; float mAlpha = 0.5f; public WatermarkParams(String mDrawText) { this.mDrawText = mDrawText; } public WatermarkParams(List mDrawTexts) { this.mDrawTexts = mDrawTexts; } }}复制代码
如何使用:
private void setWatermark() {// WatermarkDecoration.Builder builder = new WatermarkDecoration.Builder("单个水印")// .setColumnNum(3)// .setTextColor(Color.GRAY)// .setTextSize(35); //多个水印 WatermarkDecoration.Builder builder = new WatermarkDecoration.Builder(getMultiple()) .setColumnNum(3) .setTextColor(Color.GRAY) .setTextSize(35); mWatermarkDecoration = builder.builder(); mRecyclerView.addItemDecoration(mWatermarkDecoration); mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //设置水印滚动位置 mWatermarkDecoration.setScrollY(dy); } }); }复制代码
完整代码: https://github.com/hu5080126/SimpleExample/tree/master/watermark