自定义view绘制不规则圆角 渐变颜色 左右上角图标

自定义view绘制不规则圆角 渐变颜色 左右上角图标

CircularCornerColorGradientFragment类:
package com.example.androidkotlindemo2.circular

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PaintFlagsDrawFilter
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.core.graphics.toRectF
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.androidkotlindemo2.R
import com.example.androidkotlindemo2.databinding.CircularCornerColorGradientMainBinding
import com.example.androidkotlindemo2.utils.LogUtils


/**
 * Author : wn
 * Email : maoning20080809@163.com
 * Date : 2024/9/7 11:29
 * Description : 不规则圆角-颜色渐变
 */
class CircularCornerColorGradientFragment : Fragment(), View.OnClickListener{

    private lateinit var binding : CircularCornerColorGradientMainBinding
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = CircularCornerColorGradientMainBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.circularCornerColorGradientBtn4.setOnClickListener(this)
    }

    override fun onClick(v: View?) {
        v?:return
        if (v.id == R.id.circular_corner_color_gradient_btn4){
            processRecyclerView()
        }
    }

    private fun processRecyclerView(){
        var width = getScreenWidth(requireActivity()) / 3
        var list = mutableListOf<GradientBean>()
        list.add(GradientDataUtils.getGradientData1(width))
        list.add(GradientDataUtils.getGradientData2(width))
        list.add(GradientDataUtils.getGradientData3(width))
        var adapter = GradientAdapter(list)
        binding.gradientRecyclerView?.let {
            it.layoutManager = GridLayoutManager(requireActivity(), 3)
            it.adapter = adapter
        }
    }

    fun getScreenWidth(context: Context): Int {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val metrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(metrics)
        return metrics.widthPixels
    }

}
GradientAdapter类:
package com.example.androidkotlindemo2.circular

import android.widget.LinearLayout
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.androidkotlindemo2.MyApp
import com.example.androidkotlindemo2.R
import com.example.androidkotlindemo2.utils.LogUtils

/**
 * Author : wn
 * Email : maoning20080809@163.com
 * Date : 2024/9/15 16:33
 * Description : 不规则圆角-颜色渐变
 */
class GradientAdapter(list : MutableList<GradientBean>) : BaseQuickAdapter<GradientBean, BaseViewHolder>(layoutResId = R.layout.gradient_item, data = list){

    override fun convert(holder: BaseViewHolder, item: GradientBean) {

        LogUtils.d("AAA", "position : ${holder.layoutPosition}, ${item.leftUrl}")
        var circularCornerColorGradientView = CircularCornerColorGradientView(MyApp.myApp)
        circularCornerColorGradientView.setLeftUrl(item.leftUrl)
        circularCornerColorGradientView.setRightUrl(item.rightUrl)
        circularCornerColorGradientView.setBitmapScale(item.bitmapScale)
        circularCornerColorGradientView.setStartColor(item.startColor)
        circularCornerColorGradientView.setEndColor(item.endColor)
        circularCornerColorGradientView.setGradientWidth(item.gradientWidth)
        circularCornerColorGradientView.setGradientHeight(item.gradientHeight)

        var itemLayout = holder.getView<LinearLayout>(R.id.gradient_item_layout)
        itemLayout.addView(circularCornerColorGradientView)

    }

}
CircularCornerColorGradientView类:
package com.example.androidkotlindemo2.circular

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.PaintFlagsDrawFilter
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import androidx.annotation.Nullable
import androidx.core.graphics.toRectF
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.example.androidkotlindemo2.R
import com.example.androidkotlindemo2.utils.LogUtils


/**
 * Author : wn
 * Email : maoning20080809@163.com
 * Date : 2024/9/7 11:54
 * Description : 自定义颜色渐变+圆角+斜度view
 */
class CircularCornerColorGradientView : View {

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attributeSet: AttributeSet?) :this(context, attributeSet, 0)
    constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr){

    }

    private var paint = Paint()

    /**
     * 左上角图片
     */
    private var leftBitmap : Bitmap? = null

    /**
     * 右上角图片
     */
    private var rightBitmap : Bitmap? = null

    /**
     * 左上角图片地址
     */
    private var leftUrl = ""

    /**
     * 右上角图片地址
     */
    private var rightUrl = ""

    /**
     * 开始渐变颜色
     */
    private var startColor = "#B303DAC5"

    /**
     * 结束渐变颜色
     */
    private var endColor = "#B3FFFAFA"

    /**
     * 显示不规则图形宽度
     */
    private var gradientWidth = resources.getDimensionPixelSize(R.dimen.dp_100)

    /**
     * 显示不规则图形高度
     */
    private var gradientHeight = resources.getDimensionPixelSize(R.dimen.dp_50)

    /**
     * 左、右上角图片缩放比例
     */
    private var scale = 0.5f

    /**
     * 左上角图片左边距
     */
    private var leftBitmapLeftDistance = resources.getDimension(R.dimen.dp_10)

    /**
     * 左上角图片上边距
     */
    private var leftBitmapTopDistance = resources.getDimension(R.dimen.dp_10)

    /**
     * 右上角图片右边距
     */
    private var rightBitmapRightDistance = resources.getDimension(R.dimen.dp_10)

    /**
     * 右上角图片上边距
     */
    private var rightBitmapTopDistance = resources.getDimension(R.dimen.dp_24)

    /**
     * 设置圆角的半径
     */
    private val cornerRadius = resources.getDimensionPixelSize(R.dimen.dp_20)

    fun setLeftUrl(leftUrl : String){
        this.leftUrl = leftUrl
    }

    fun setRightUrl(rightUrl : String){
        this.rightUrl = rightUrl
    }

    fun setStartColor(startColor : String){
        this.startColor = startColor
    }

    fun setEndColor(endColor : String){
        this.endColor = endColor
    }

    fun setBitmapScale(scale : Float){
        this.scale = scale
    }

    /**
     * 左上角图片左边距
     */
    fun setLeftBitmapLeftDistance(leftBitmapLeftDistance : Float){
        this.leftBitmapLeftDistance = leftBitmapLeftDistance
    }

    /**
     * 左上角图片上边距
     */
    fun setLeftBitmapTopDistance(leftBitmapTopDistance : Float){
        this.leftBitmapTopDistance = leftBitmapTopDistance
    }

    /**
     * 显示不规则图形宽度
     */
    fun setGradientWidth(gradientWidth : Int){
        this.gradientWidth = gradientWidth
    }

    /**
     * 显示不规则图形高度
     */
    fun setGradientHeight(gradientHeight : Int){
        this.gradientHeight = gradientHeight
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //设置自定义view的宽度、高度
        setMeasuredDimension(gradientWidth, gradientHeight)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        canvasBitmap(canvas)

        //加载、绘制左上角图片
        if(leftBitmap == null){
            loadLeftBitmap()
        } else {
            leftBitmap?.let {
                canvas.drawBitmap(it, leftBitmapLeftDistance, leftBitmapTopDistance, paint)
            }
        }

        //加载、绘制右上角图片
        if(rightBitmap == null){
            loadRightBitmap()
        } else {
            rightBitmap?.let {
                var rightDistance = (gradientWidth - it.width - rightBitmapRightDistance).toFloat()
                canvas.drawBitmap(it, rightDistance, rightBitmapTopDistance, paint)
            }
        }

    }


    /**
     * 等比压缩图片
     */
    private fun zoomBitmap(bitmap: Bitmap) : Bitmap{
        var width = bitmap.width.toFloat()
        var height = bitmap.height.toFloat()
        var resultWidth = (width * scale).toInt()
        var resultHeight = (height * scale).toInt()
        var resultBitmap = Bitmap.createScaledBitmap(bitmap, resultWidth, resultHeight, false)
        return resultBitmap
    }

    /**
     * 绘制渐变斜度-圆角
     */
    private fun canvasBitmap(canvas: Canvas){
        var originalBitmap = getOriginalBitmap()
        LogUtils.i("AAA", "canvasBitmap : ${originalBitmap.width} , ${originalBitmap.height} , ${leftUrl} , ${rightUrl}")
        var roundedCornerBitmap = getRoundedCornerBitmap3(originalBitmap, cornerRadius)
        canvas.drawBitmap(roundedCornerBitmap, 0f, 0f, paint)
    }

    private fun getOriginalBitmap() : Bitmap{
        val colors = intArrayOf(
            Color.parseColor(startColor),
            Color.parseColor(endColor)
        )

        //颜色渐变
        val gradientDrawable = GradientDrawable()
        gradientDrawable.gradientType = GradientDrawable.LINEAR_GRADIENT
        gradientDrawable.orientation = GradientDrawable.Orientation.TOP_BOTTOM
        gradientDrawable.colors = colors

        // 创建一个等大小的空Bitmap
        var bitmap = Bitmap.createBitmap(gradientWidth, gradientHeight, Bitmap.Config.ARGB_8888);
        var canvas = Canvas(bitmap);

        // 绘制Drawable到Bitmap
        gradientDrawable.setBounds(0, 0, gradientWidth, gradientHeight);
        gradientDrawable.draw(canvas);
        return bitmap
    }


    /**
     * 使用lineTo绘制圆角
     */
    private fun createRoundedCornerPath3(rect: RectF, cornerRadius: Float): Path {
        val path = Path()
        path.moveTo(rect.left + cornerRadius, rect.top) // 起点在左上角
        path.lineTo(rect.right - cornerRadius, rect.top+ cornerRadius*1) // 直线到右上角
        // 使用quadTo方法添加圆角
        path.quadTo(rect.right, rect.top+ cornerRadius*1, rect.right, rect.top + cornerRadius*2)
        path.lineTo(rect.right, rect.bottom - cornerRadius)
        path.quadTo(rect.right, rect.bottom, rect.right - cornerRadius, rect.bottom)
        path.lineTo(rect.left + cornerRadius, rect.bottom)
        path.quadTo(rect.left, rect.bottom, rect.left, rect.bottom - cornerRadius)
        path.lineTo(rect.left, rect.top + cornerRadius)
        path.quadTo(rect.left, rect.top, rect.left + cornerRadius, rect.top)
        path.close()
        return path
    }

    private fun getRoundedCornerBitmap3(bitmap: Bitmap, cornerRadius: Int): Bitmap {
        val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)
        //canvas 设置抗锯齿
        canvas.drawFilter = PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
        val paint = Paint()
        val rect = Rect(0, 0, bitmap.width, bitmap.height)
        //是用来防止边缘的锯齿,
        paint.isAntiAlias = true
        //函数是用来对位图进行滤波处理
        paint.isFilterBitmap = true
        var path = createRoundedCornerPath3(rect.toRectF(), cornerRadius.toFloat())
        canvas.drawPath(path, paint)
        paint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.SRC_IN))
        canvas.drawBitmap(bitmap, rect, rect, paint)

        return output
    }

    /**
     * 获取左上角图片
     */
    private fun loadLeftBitmap(){
        if(TextUtils.isEmpty(leftUrl)){
            return
        }
        Glide.with(context)
            .asBitmap()
            .load(leftUrl)
            .into(object : SimpleTarget<Bitmap?>() {
                override fun onResourceReady(
                    resource: Bitmap,
                    @Nullable transition: Transition<in Bitmap?>?
                ) {
                    leftBitmap = zoomBitmap(resource)
                    invalidate()
                }

                override fun onLoadFailed(errorDrawable: Drawable?) {
                    super.onLoadFailed(errorDrawable)
                }
            })
    }

    /**
     * 获取右上角图片
     */
    private fun loadRightBitmap(){
        if(TextUtils.isEmpty(rightUrl)){
            return
        }
        Glide.with(context)
            .asBitmap()
            .load(rightUrl)
            .into(object : SimpleTarget<Bitmap?>() {
                override fun onResourceReady(
                    resource: Bitmap,
                    @Nullable transition: Transition<in Bitmap?>?
                ) {
                    rightBitmap = zoomBitmap(resource)
                    invalidate()
                }

                override fun onLoadFailed(errorDrawable: Drawable?) {
                    super.onLoadFailed(errorDrawable)
                }
            })
    }

}
GradientDataUtils类:
package com.example.androidkotlindemo2.circular

/**
 * Author : wn
 * Email : maoning20080809@163.com
 * Date : 2024/9/15 16:58
 * Description :
 */
object GradientDataUtils {

    fun getGradientData1(width : Int) : GradientBean{
        var gradientBean = GradientBean()
        gradientBean.leftUrl = "https://img.duoziwang.com/2016/09/02/16135043775.jpg"
        gradientBean.rightUrl = "https://img.woyaogexing.com/2016/03/18/c4df209cad1840bb%21200x200.jpg"
        gradientBean.bitmapScale = 0.3f
        gradientBean.startColor = "#B303DAC5"
        gradientBean.endColor = "#B3FFFAFA"
        gradientBean.gradientWidth = width
        gradientBean.gradientHeight = (width * 0.6).toInt()
        return gradientBean
    }

    fun getGradientData2(width : Int) : GradientBean{
        var gradientBean = GradientBean()
        gradientBean.leftUrl = "http://img.duoziwang.com/2016/11/21/13565441404.jpg"
        gradientBean.rightUrl = "http://img.duoziwang.com/2016/11/29/220134634.jpg"
        gradientBean.bitmapScale = 0.3f
        gradientBean.startColor = "#B3BB86FC"
        gradientBean.endColor = "#B3FFDEAD"
        gradientBean.gradientWidth = width
        gradientBean.gradientHeight = (width * 0.6).toInt()
        return gradientBean
    }

    fun getGradientData3(width : Int) : GradientBean{
        var gradientBean = GradientBean()
        gradientBean.leftUrl = "https://tupian.qqw21.com/article/UploadPic/2018-3/20183817105179447.jpg"
        gradientBean.rightUrl = "http://img.duoziwang.com/2021/01/1618554889818120.jpg"
        gradientBean.bitmapScale = 0.3f
        gradientBean.startColor = "#B3FF6347"
        gradientBean.endColor = "#B3FFD700"
        gradientBean.gradientWidth = width
        gradientBean.gradientHeight = (width * 0.6).toInt()
        return gradientBean
    }

}
circular_corner_color_gradient_main布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:orientation="vertical">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textColor="@color/red"
        android:textSize="30sp"
        android:text="不正规圆角-颜色渐变"/>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">


        <Button
            android:id="@+id/circular_corner_color_gradient_btn4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:layout_alignParentRight="true"
            android:layout_gravity="center"
            android:text="渐变+圆角+图标 RecyclerView"/>

    </LinearLayout>



    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:textSize="30sp"
        android:textColor="@color/purple_200"
        android:text="RecyclerView列表"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/gradient_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


</LinearLayout>
gradient_item布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/gradient_item_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">

</LinearLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

六毛六66

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值