- 效果如下:
效果圖.jpg
實(shí)現(xiàn)思路:
用canvas.drawPath(path,paint)先繪制一個(gè)六邊形的形狀。 然后在結(jié)合BitmapShader方法將
我們的圖片bitmap設(shè)置給畫(huà)筆就ok了欺劳。
例子:
val bitmapShader = BitmapShader(Bitamp, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR)
//計(jì)算縮放比例
var mScale = sourceWidth.toFloat() / Bitamp.width.toFloat()
val matrix = Matrix()
matrix.setScale(mScale, mScale)
bitmapShader.setLocalMatrix(matrix)
var mPaint = Paint()
mPaint.shader = bitmapShader
Canvas.drawPath(Path, mPaint)
第一步測(cè)量view的寬高
我們的六邊形是一個(gè)正六邊形 所以寬高要一樣。
這里還有個(gè)知識(shí)點(diǎn):由于畫(huà)筆具有寬度,所以我們?cè)谠O(shè)定view的寬高的時(shí)候要考慮到畫(huà)筆寬度的那部分值招拙,不然就會(huì)出現(xiàn)我們畫(huà)出來(lái)的view有一部分會(huì)顯示不出來(lái)的情況前联。
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(handleMeasure(widthMeasureSpec), handleMeasure(heightMeasureSpec))
}
/**
* 處理寬高
*/
private fun handleMeasure(measureSpec: Int): Int {
var specMode: Int = MeasureSpec.getMode(measureSpec)
var specSize: Int = MeasureSpec.getSize(measureSpec)
var result = 100
result = when (specMode) {
MeasureSpec.EXACTLY -> {
specSize
}
else -> {
min(result, specSize)
}
}
parentWidth = result + sixStroke.toInt() * 2 //這里又加了個(gè) sixStroke * 2 就是考慮到了畫(huà)筆的寬度
return parentWidth
}
到這里我們的view的大小就確定好了。
第二步繪制一個(gè)六邊形的形狀
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
var circlePointX = parentWidth / 2
var radian60 = 60 * Math.PI / 180
var xLength = circlePointX * sin(radian60)
var yLength = circlePointX * cos(radian60)
path.reset()
path.moveTo(circlePointX.toFloat(), sixStroke / 2)
path.lineTo(circlePointX.toFloat() + xLength.toFloat(), yLength.toFloat())
path.lineTo(
circlePointX.toFloat() + xLength.toFloat(),
circlePointX + yLength.toFloat()
)
path.lineTo(circlePointX.toFloat(), parentWidth.toFloat() - sixStroke / 2)
path.lineTo(
circlePointX.toFloat() - xLength.toFloat(),
circlePointX + yLength.toFloat()
)
path.lineTo(circlePointX.toFloat() - xLength.toFloat(), yLength.toFloat())
path.close()
canvas.drawPath(path, mPaint)
}
}
至此一個(gè)六邊形就繪制完畢僚楞。
第三步優(yōu)化我們的六邊形 讓他兼顧展示網(wǎng)絡(luò)圖片的功能勤晚。
先引入我們的Glide圖片加載框架:
/**
* glide圖片加載
*/
api "com.github.bumptech.glide:glide:4.11.0"
annotationProcessor "com.github.bumptech.glide:compiler:2.0"
自定義Glide加載圖片的transform方法:
class PentagonaltTransform(val width: Float) : BitmapTransformation() {
val path = Path()
lateinit var mCanvas: Canvas
val mPaint by lazy {
Paint().apply {
isAntiAlias = true
color = Color.RED
strokeWidth = 10f
strokeCap = Paint.Cap.ROUND
pathEffect = CornerPathEffect(10f)
}
}
override fun updateDiskCacheKey(p0: MessageDigest) {
}
override fun transform(
pool: BitmapPool,
source: Bitmap,
outWidth: Int,
outHeight: Int
): Bitmap {
var result: Bitmap? = pool[width.toInt(), width.toInt(), Bitmap.Config.ARGB_8888]
if (result == null) {
result = Bitmap.createBitmap(width.toInt(), width.toInt(), Bitmap.Config.ARGB_8888)
}
mCanvas = Canvas(result!!)
var circlePointX = width / 2
var radian60 = 60 * Math.PI / 180
var xLength = circlePointX * kotlin.math.sin(radian60)
var yLength = circlePointX * kotlin.math.cos(radian60)
path.reset()
path.moveTo(circlePointX.toFloat(), 0f)
path.lineTo(circlePointX.toFloat() + xLength.toFloat(), yLength.toFloat())
path.lineTo(circlePointX.toFloat() + xLength.toFloat(), circlePointX + yLength.toFloat())
path.lineTo(circlePointX.toFloat(), circlePointX.toFloat() * 2)
path.lineTo(circlePointX.toFloat() - xLength.toFloat(), circlePointX + yLength.toFloat())
path.lineTo(circlePointX.toFloat() - xLength.toFloat(), yLength.toFloat())
path.close()
mPaint.shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
mPaint.isAntiAlias = true
mCanvas!!.drawPath(path, mPaint)
return result!! //切記這里不能返回那個(gè)source的bitmap 要返回我們創(chuàng)建的只有寬高信息的bitmap
}
}
使用自定義的transform的方法:
Glide.with(this).load(url)
// .apply(RequestOptions.bitmapTransform(PentagonaltTransform()))
.transform(PentagonaltTransform(這里寫(xiě)ImageView的寬高))
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(p0: GlideException?, p1: Any?, p2: Target<Drawable>?, p3: Boolean): Boolean {
//當(dāng)遇到網(wǎng)絡(luò)圖片加載錯(cuò)的時(shí)候 去加載默認(rèn)的圖片
setDefaultDrawable()
return false
}
override fun onResourceReady(p0: Drawable?, p1: Any?, p2: Target<Drawable>?, p3: DataSource?, p4: Boolean): Boolean {
return false
}
}).into(this)
至此自定義加載網(wǎng)絡(luò)圖片的六邊形TransForm完成。
全部代碼已經(jīng)上傳至Github:https://github.com/1169927533/BaseMavenProject/blob/master/module_customview/src/main/java/com/pince/module_customview/sixshape/PentagonalView.kt
使用方法:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
dependencies {
implementation 'com.github.1169927533.BaseMavenProject:module_customview:1.4.1'
}