Android自定义View:仿企业微信,钉钉实现倾斜水印效果

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/DeMonliuhui/article/details/91445794

问题

企业微信和钉钉的部分页面有倾斜角度显示用户信息的水印,本文模仿实现效果如下:

思路

1.根据要显示的文字内容,绘制图片,然后将画布旋转-45°,生成bitmap。
2.获取要显示水印的Activty的RootView,在RootView上添加一个view用于显示水印图片。
3.根据需求给view布局文件设置透明度,android:alpha="0.8"

实现

WaterMarkUtil.kt

object WaterMarkUtil {

    /**
     *  Activity中显示水印,在onCreate的setContentView方法后调用
     *  多个界面显示水印可在BaseActivity中统一调用
     *  @param activity
     * @param string 水印文字内容
     */
    fun showWatermarkView(activity: Activity, string: String) {
        val rootView: ViewGroup = activity.window.decorView.findViewById(android.R.id.content)
        val framView: View = LayoutInflater.from(activity).inflate(R.layout.layout_watermark, null)
        val wm: WindowManager = activity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val dm = DisplayMetrics()
        wm.defaultDisplay.getMetrics(dm)
        val width = dm.widthPixels         // 屏幕宽度(像素)
        val height = dm.heightPixels       // 屏幕高度(像素)
        framView.ivWm.setImageDrawable(getMarkTextBitmapDrawable(activity, string, width, height))
        //可对水印布局进行初始化操作
        rootView.addView(framView)
    }

    /**
     * 获得文字水印的图片
     * @param width
     * @param height
     * @return
     */
    private fun getMarkTextBitmapDrawable(gContext: Context, gText: String, width: Int, height: Int): Drawable? {
        val bitmap = getMarkTextBitmap(gContext, gText, width, height)
        if (bitmap != null) {
            val drawable = BitmapDrawable(gContext.resources, bitmap)
            drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)
            drawable.setDither(true)
            return drawable
        }
        return null
    }

    private fun getMarkTextBitmap(gContext: Context, gText: String, width: Int, height: Int): Bitmap? {
        val textSize: Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 18f, gContext.resources.displayMetrics)
        val inter: Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25f, gContext.resources.displayMetrics)

        val sideLength: Int = if (width > height) {
            Math.sqrt((2 * (width * width)).toDouble()).toInt()
        } else {
            Math.sqrt((2 * (height * height)).toDouble()).toInt()
        }


        val paint = Paint(ANTI_ALIAS_FLAG)
        val rect = Rect()
        paint.textSize = textSize
        //获取文字长度和宽度
        paint.getTextBounds(gText, 0, gText.length, rect)

        val strwid = rect.width()
        val strhei = rect.height()

        var markBitmap: Bitmap? = null
        try {
            markBitmap = Bitmap.createBitmap(sideLength, sideLength, Bitmap.Config.ARGB_4444)
            val canvas = Canvas(markBitmap)
            //创建透明画布
            canvas.drawColor(Color.TRANSPARENT)

            paint.color = Color.BLACK
            paint.alpha = (0.1 * 255f).toInt()
            // 获取跟清晰的图像采样
            paint.isDither = true
            paint.isFilterBitmap = true

            //先平移,再旋转才不会有空白,使整个图片充满
            if (width > height) {
                canvas.translate(width.toFloat() - sideLength.toFloat() - inter, sideLength - width + inter)
            } else {
                canvas.translate(height.toFloat() - sideLength.toFloat() - inter, sideLength - height + inter)
            }

            //将该文字图片逆时针方向倾斜45度
            canvas.rotate((-45).toFloat())

            var i = 0
            while (i <= sideLength) {
                var count = 0
                var j = 0
                while (j <= sideLength) {
                    if (count % 2 == 0) {
                        canvas.drawText(gText, i.toFloat(), j.toFloat(), paint)
                    } else {
                        //偶数行进行错开
                        canvas.drawText(gText, (i + strwid / 2).toFloat(), j.toFloat(), paint)
                    }
                    j = (j.toFloat() + inter + strhei.toFloat()).toInt()
                    count++
                }
                i = (i.toFloat() + strwid.toFloat() + inter).toInt()
            }
            canvas.save()
        } catch (e: OutOfMemoryError) {
            if (markBitmap != null && !markBitmap.isRecycled) {
                markBitmap.recycle()
                markBitmap = null
            }
        }

        return markBitmap
    }

}

layout_watermark.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:alpha="0.8">

	<ImageView
		android:id="@+id/ivWm"
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:scaleType="fitXY" />
</LinearLayout>

使用

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //为当前Activity添加水印
        WaterMarkUtil.showWatermarkView(this, "Hello Word!")
    }
}

代码

GitHub:https://github.com/MyAndroidDemo/WaterMark

猜你喜欢

转载自blog.csdn.net/DeMonliuhui/article/details/91445794