/**
* Created by guc on 2020/6/12.
* Description:水印
*/
class WaterMarkView(context: Context, attrs: AttributeSet?, defStyle: Int) :
View(context, attrs, defStyle) {
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
constructor(context: Context) : this(context, null, 0)
companion object {
const val TAG = "WaterMarkView"
const val DEFAULT_RADIAN: Float = (PI / 6).toFloat()
}
var markText: CharSequence = "水印"
private val path = Path()
private var lineHeight = 0 //px
private var markerTextSize = 0f
private var singleMarkerWidth = 0
private var singleMarkerHeight = 0
private var markerSpace = 0//間距
private var deltaFixSpace = 0//修正間距
var radian = DEFAULT_RADIAN//弧度
private var repeatCountX = 1
private var repeatCountY = 1
private var repeatSpace = 1
private val paint = Paint().apply {
isAntiAlias = true
color = Color.DKGRAY
style = Paint.Style.FILL
}
init {
val a = context.obtainStyledAttributes(attrs, R.styleable.WaterMarkView)
markText = a.getString(R.styleable.WaterMarkView_markerText) ?: "水印"
LogG.loge(TAG, "獲取前:$lineHeight")
lineHeight = a.getDimensionPixelOffset(
R.styleable.WaterMarkView_lineHeight,
dp2px(50f)
)
LogG.loge(TAG, "獲取後:$lineHeight")
markerTextSize = a.getDimension(R.styleable.WaterMarkView_markerTextSize, 48f)
markerSpace =
a.getDimension(R.styleable.WaterMarkView_markerSpace, dp2px(30f).toFloat()).toInt()
deltaFixSpace =
a.getDimension(R.styleable.WaterMarkView_fixSpace, markerSpace.toFloat() / 2).toInt()
radian = a.getFloat(R.styleable.WaterMarkView_radian, DEFAULT_RADIAN)
a.recycle()
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val rectText = Rect()
paint.textSize = markerTextSize
paint.getTextBounds(markText.toString(), 0, markText.toString().length, rectText)
singleMarkerWidth = rectText.width()
singleMarkerHeight = rectText.height()
val space = "a"
paint.getTextBounds(space, 0, space.length, rectText)
repeatSpace = markerSpace / rectText.width()
repeatCountX = ceil(width * 1.0 / cos(radian) / (singleMarkerWidth + markerSpace)).toInt()
repeatCountY = floor(height * 1.0 / lineHeight).toInt()
val itemStdHeight = getItemHeight()
for (i in 1..repeatCountY) {
path.reset()
path.moveTo(0f + deltaFixSpace, i * lineHeight.toFloat())
val x = getEndX(itemStdHeight, i) + deltaFixSpace
val y = getEndY(itemStdHeight, i)
path.lineTo(x, y)
canvas.drawTextOnPath(getLineText(), path, 0f, 0f, paint)
}
}
private fun isEnoughHeight(itemHeight: Float, times: Int) = itemHeight <= times * lineHeight
private fun getEndX(itemHeight: Float, times: Int): Float =
if (isEnoughHeight(
itemHeight,
times
)
) width.toFloat() else (lineHeight * times * 1.0f / tan(
radian
))
private fun getEndY(itemHeight: Float, times: Int): Float =
if (isEnoughHeight(itemHeight, times)) (lineHeight * times - itemHeight) else 0f
private fun getItemHeight(): Float {
return width * tan(radian)
}
private fun getLineText(): String {
val sb = StringBuilder()
repeat(repeatCountX) {
sb.append(markText)
repeat(repeatSpace) {
sb.append(" ")
}
}
return sb.toString()
}
private fun dp2px(dipValue: Float): Int {
val scale = resources.displayMetrics.density
return (dipValue * scale + 0.5f).toInt()
}
}
<declare-styleable name="WaterMarkView">
<attr name="markerText" format="reference|string" /> <!--水印文本-->
<attr name="lineHeight" format="dimension" /> <!--水印行間距-->
<attr name="markerTextSize" format="dimension" /> <!--水印字體大小-->
<attr name="markerSpace" format="dimension" /> <!--水印間距-->
<attr name="fixSpace" format="dimension" /> <!--界面左側邊距設置-->
<attr name="radian" format="float" /> <!--傾斜角度-->
</declare-styleable>
- 創建水印佈局layout_water_mark.xml
<?xml version="1.0" encoding="utf-8"?>
<com.kframe.widget.WaterMarkView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.2"
app:lineHeight="80dp"
app:markerSpace="50dp"
app:markerText=""
app:radian="0.524" />
object WaterMarkUtil{
private const val VIEW_TAG = "view_tag"
var enable = false
var text = "水印"
//在Activity的onActivityStart()方法調用
fun onActivityStart(activity:Activity){
val rootView = activity.window.decorView.findViewById<ViewGroup>(android.R.id.content)
if (enable && text.isNotEmpty() && rootView.findViewWithTag<View>(VIEW_TAG) == null) {
val waterMarkView =
LayoutInflater.from(activity)
.inflate(R.layout.layout_water_mark, null) as WaterMarkView
waterMarkView.tag = VIEW_TAG
waterMarkView.markText = text
rootView.addView(waterMarkView)
}
}
}
//開啓水印,並設置水印文本
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WaterMarkUtil.enable = true
WaterMarkUtil.text = "自定義水印"
}
//添加水印
override fun onStart() {
super.onStart()
WaterMarkUtil.onActivityStart(this)
}