Kotlin 背景圓頭像圖
1.需求:大部分的頭像選擇更換時都採取這樣的功能,半透明的蒙版,中間一個正方形的選取框,底圖隨意移動縮放,確定後擷取為背景頭像。網易雲,微信都是如此
2.實現:
1:程式碼:
package sss
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import com.example.sosrcpro.R
class CyclerView:View{
//圖片來源
private var bitmap:Bitmap? = null
private var paint:Paint? = null
private var bitmapShader:BitmapShader? = null
private var bitmapPaint:Paint? = null
private var bitmatLeft = 0
private var bitmapTop = 0
private var roundPaint:Paint? =null
private var viewWidthHalf = 0F
private var viewHeihtHalf = 0F
var starX = 0F
var starY = 0F
var roundRadiu = 0F
var detector:ScaleGestureDetector? = null
var detectorListener:ScaleGestureDetector.OnScaleGestureListener? = null
var fixedRadiu = 0F
constructor(context:Context):this(context,null){
}
constructor(context: Context,attributeSet: AttributeSet?):this(context,attributeSet,0){
}
constructor(context: Context,attributeSet: AttributeSet?,style:Int):super(context,attributeSet,style){
paint = Paint()
bitmapPaint = Paint()
roundPaint = Paint()
paint?.apply {
setAntiAlias(true)
}
bitmap = BitmapFactory.decodeResource(resources, R.mipmap.timg)
detectorListener = object:ScaleGestureDetector.OnScaleGestureListener{
//返回true才能進入onScale
override fun onScaleBegin(detector: ScaleGestureDetector?): Boolean {
return true
}
override fun onScaleEnd(detector: ScaleGestureDetector?) {
}
override fun onScale(detector: ScaleGestureDetector): Boolean {
var currentS = detector.currentSpan
var currentX = detector.currentSpanX
var currentY = detector.currentSpanY
var currentScale = detector.scaleFactor
Log.d("save","currentS:"+currentS.toString())
Log.d("save","currentScale:"+currentScale.toString())
if(currentScale>1)
scaleBitmapByTouch(1.1F)
else if(currentScale<1){
scaleBitmapByTouch(0.9F)
}
return true
}
}
detector = ScaleGestureDetector(getContext(),detectorListener)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
viewWidthHalf = measuredWidth/2F
viewHeihtHalf = measuredHeight/2F
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
var srcrect = Rect(0, 0, bitmap!!.getWidth(), bitmap!!.getHeight())
//單指移動圖片
var dscrect = Rect(bitmatLeft, bitmapTop, bitmap!!.getWidth()+bitmatLeft, bitmap!!.getHeight()+bitmapTop)
//繪製底圖
canvas?.drawBitmap(bitmap!!, srcrect, dscrect, bitmapPaint)
paint?.setColor(Color.parseColor("#80666666"))
var radiu = canvas?.width!! /3F
fixedRadiu = radiu/2F
var layerId = canvas.saveLayer(0F,0F,canvas.width*1F,canvas.height*1F,null,Canvas.ALL_SAVE_FLAG)
//繪製灰色半透明的蒙版
canvas?.drawRect(0F,0F,canvas.width*1F,canvas.height*1F,paint!!)
//DST_OUT:取下層繪製非交集部分。不顯示上層(由於圓圈部分存在交集,不顯示這下層部分,就鏤空了,
// 進而顯示底圖,而底圖其他部分顯示其他非交集下層部分)
paint?.setXfermode(PorterDuffXfermode(PorterDuff.Mode.DST_OUT))
paint?.setColor(Color.BLUE)
//畫圓,通過透底得到鏤空的底圖
canvas?.drawCircle(canvas.width/2F,canvas.height/2F,fixedRadiu,paint!!)
paint?.setXfermode(null)
canvas?.restoreToCount(layerId)
}
fun setBitmap(bitmap:Bitmap){
this.bitmap = bitmap
invalidate()
}
fun getBitmapFormView():Bitmap{
return bitmap!!
}
fun scaleBitmapByTouch(scale:Float){
var matrix = Matrix()
matrix.setScale(scale,scale)
bitmap = Bitmap.createBitmap(bitmap!!,0,0,bitmap!!.width,bitmap!!.height,matrix,true)
}
fun getCircleBitmap( bitmap:Bitmap) {
var circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
var canvas = Canvas(circleBitmap)
var paint = Paint()
var rect = Rect(0, 0, bitmap.getWidth(), bitmap.getHeight())
var rectF = RectF(rect);
var roundRa = 0.0f
if (bitmap.getWidth() > bitmap.getHeight()) {
roundRa = bitmap.getHeight() / 2.0f
} else {
roundRa = bitmap.getWidth() / 2.0f
}
}
//是頻繁呼叫的,starX,starY的初始化要放在類中,不是在函式中,否則不管是任何觸控型別都設定為0了。
//加上放大縮小,範圍控制,截圖,儲存。
override fun onTouchEvent(event: MotionEvent?): Boolean {
detector!!.onTouchEvent(event)
var touchType = event!!.actionMasked
when(touchType){
//單指,多指
MotionEvent.ACTION_DOWN->{
starX =event.x
starY = event.y
Log.e("native","ACTION_DOWN")
}
//單指,多指
MotionEvent.ACTION_MOVE->{
var x =event.x
var y = event.y
var xxx = x-starX
var yyy =y-starY
starX =x
starY = y
setBitmapPosition(bitmatLeft+xxx,bitmapTop+yyy)
Log.e("native","ACTION_MOVE")
var pointCount = event.pointerCount
if(pointCount==2){
}
}
//單指,多指
MotionEvent.ACTION_UP->{
Log.e("native","ACTION_UP")
}
//單指多指都是ACTION_MOVE
//多指
MotionEvent.ACTION_POINTER_DOWN->{
Log.e("native","ACTION_POINTER_DOWN")
}
//多指
MotionEvent.ACTION_POINTER_UP->{
Log.e("native","ACTION_POINTER_UP")
}
}
return true
}
fun setBitmapPosition(left:Float,top:Float){
bitmatLeft = left.toInt()
bitmapTop = top.toInt()
invalidate()
}
fun getRoundBitmap(radiu:Float):Bitmap{
//畫布設定為邊長為圓框的半徑
var output = Bitmap.createBitmap(fixedRadiu.toInt()*2,fixedRadiu.toInt()*2,Bitmap.Config.ARGB_8888)
var canvas = Canvas(output)
//原圖
var srcRect = Rect(0,0,bitmap!!.width,bitmap!!.height)
//移動,放置的位置又這個確定,看到的圓框與新的左上角的圓要效果一樣。相當於多移動一部分(即兩個圓的距離)
var dscRect = Rect(bitmatLeft-(viewWidthHalf.toInt()-fixedRadiu.toInt()),bitmapTop-(viewHeihtHalf.toInt()-fixedRadiu.toInt()),bitmap!!.width+bitmatLeft-(viewWidthHalf.toInt()-fixedRadiu.toInt()),bitmap!!.height+bitmapTop-(viewHeihtHalf.toInt()-fixedRadiu.toInt()))
//PorterDuff.Mode.SRC_IN 後不管背景顏色如何,我這都是灰色的。
canvas.drawARGB(0,255,0,0)
roundPaint!!.color = Color.parseColor("#ff424242")
//圓的中心座標不變,移動圖片進行繪製即可。
canvas.drawCircle(fixedRadiu,fixedRadiu,fixedRadiu,roundPaint!!)
roundPaint!!.setXfermode(PorterDuffXfermode(PorterDuff.Mode.SRC_IN))
canvas.drawBitmap(bitmap!!,srcRect,dscRect,roundPaint)
roundPaint!!.setXfermode(null) //每次繪製完畢後都應重置為null
//二次擷取
return output
}
fun saveBitmap():Bitmap{
return getRoundBitmap(fixedRadiu)
}
}
2效果:
這裡的縮放還沒有限制,單指移動也還沒限制,懶得弄了,這只是練練手,懂個思路就行,其實大概也能用了,哈哈哈哈哈哈哈哈哈。
程式碼改了,效果圖沒改,程式碼改後截圖大小剛好和圓框大小一致。原來的是和原圖大小一樣,這樣就沒辦法直接用了。
相關文章
- Flutter 圓形/圓角頭像Flutter
- CircleImageView 圓形圖片頭像實現View
- android裁剪圓型頭像Android
- Android之圓形頭像裁切Android
- Android 自定義圓形頭像Android
- Android自定義圓形頭像Android
- 《Android開發卷——設定圓形頭像,Android擷取圓形圖片》Android
- android圓形頭像的選擇和剪下並儲存出圓形圖片Android
- 使用 RoundedBitmapDrawable 建立圓角頭像詳解
- 基於 GD 庫生成圓形頭像
- 自定義頭像圓角控制元件控制元件
- 自定義圓形ImageView(仿QQ頭像)View
- Android 圓形頭像 自己動手Android
- 自定義ImageView完成圓形頭像自定義View
- Android 圓形頭像 相簿和拍照裁剪選取Android
- 小程式之open-data userAvatarUrl頭像做圓角
- QQ群頭像 微信群頭像 多圖合併框架實現框架
- CSS不用背景圖片實現優惠券樣式反圓角,凹圓角,反向半圓角,並且背景漸變CSS
- 微信小程式獲取使用者頭像修改為圓形微信小程式
- 頭像
- 擷取圖片生成頭像外掛
- html5呼叫攝像頭截圖HTML
- laravel圖片/頭像上傳通用方法Laravel
- C# 模仿微信生成九宮圖頭像C#
- 攝像頭背後的應用–資訊圖
- Android圖片上傳(頭像裁切+原圖原樣)Android
- C#使用OpenCV剪下圖片中的人物頭像C#OpenCV
- JavaCV的攝像頭實戰之四:抓圖Java
- Android 自定義圓形旋轉進度條,仿微博頭像載入效果Android
- WebRTC從攝像頭獲取圖片傳入canvasWebCanvas
- 攝像頭操作指南
- 二十一、CSS3圓角半徑/多背景/背景尺寸CSSS3
- ToDesk勾上攝像頭會看到我嗎?如何關閉攝像頭
- WPF呼叫攝像頭,對圖片相似度識別 1.0
- 為什麼介面設計中,使用者的個人頭像大多是圓形的?
- 安卓呼叫攝像頭拍照安卓
- Android呼叫攝像頭Android
- .NET 攝像頭採集