Android 自定义ImageView实现圆角

这篇具有很好参考价值的文章主要介绍了Android 自定义ImageView实现圆角。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求描述:

        实现一个带圆角的imageView,要求自定义view方式实现。

需求分析:

        我们可以自定义一个view,继承ImageView,并只需要重写ImageView的onDraw()方法即可。带圆角意味着要把控件的四个顶角做一个裁切。由于不能影响imageview主体的正常绘制, 想到了可以在执行super.onDraw()方法之前进行对画布canvas的裁切。 这样接下来绘制的控件就只会在裁切范围内。从而实现了我们的需求。

代码实现:

实现流程步骤

1、定义好自定义view用到的的属性;

2、自定义view,使之继承ImageView,并在其构造函数中获取自定义属性值;

3、重写ImageView的onDraw()方法, 在执行super.onDraw()之前利用Path创建一个路径对象,然后使用画布沿着path路径裁切;

4、调用super.onDraw()绘制imageview的主体内容

1、定义自定义view属性:

在attrs.xml中声明如下

<resources>
    <declare-styleable name="RoundImageView">
        <attr name="radius" format="dimension"/>
        <attr name="leftTopRadius" format="dimension"/>
        <attr name="rightTopRadius" format="dimension"/>
        <attr name="leftBottomRadius" format="dimension"/>
        <attr name="rightBottomRadius" format="dimension"/>
    </declare-styleable>
    ...
</resources>

        这里有一点需要注意下,控件的尺寸相关属性的类型需要使用dimension,而不是int或float。

2、自定义view获取属性值 & 重写onDraw方法

class RoundImageView: AppCompatImageView {

    private var rightBottomRadius: Int
    private var leftBottomRadius: Int
    private var rightTopRadius: Int
    private var leftTopRadius: Int
    private var radius: Int =0

    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) {
        var typeArray = context.obtainStyledAttributes(attributeSet, R.styleable.RoundImageView)
        val defaultRadius = 0
        radius = typeArray.getDimensionPixelOffset(R.styleable.RoundImageView_radius, defaultRadius)
        leftTopRadius = typeArray.getDimensionPixelOffset(
            R.styleable.RoundImageView_leftTopRadius,
            defaultRadius
        )
        rightTopRadius = typeArray.getDimensionPixelOffset(
            R.styleable.RoundImageView_rightTopRadius,
            defaultRadius
        )
        leftBottomRadius = typeArray.getDimensionPixelOffset(
            R.styleable.RoundImageView_leftBottomRadius,
            defaultRadius
        )
        rightBottomRadius = typeArray.getDimensionPixelOffset(
            R.styleable.RoundImageView_rightBottomRadius,
            defaultRadius
        )
        if (radius != 0) {
            if (leftTopRadius == 0) {
                leftTopRadius = radius
            }
            if (rightTopRadius == 0) {
                rightTopRadius = radius;
            }
            if (leftBottomRadius == 0) {
                leftBottomRadius = radius;
            }
            if (rightBottomRadius == 0) {
                rightBottomRadius = radius;
            }
        }
        typeArray.recycle()
    }

    override fun onDraw(canvas: Canvas?) {
        // 保证图片宽高大于圆角宽高, 获取圆角的宽高
        // 取横着大的长度
        val maxLeft = Math.max(leftTopRadius, leftBottomRadius)
        val maxRight = Math.max(rightTopRadius, rightBottomRadius)
        val minWidth = maxLeft + maxRight
        // 取竖着大的长度
        val maxTop = Math.max(leftTopRadius, rightTopRadius)
        val maxBottom = Math.max(leftBottomRadius, rightBottomRadius)
        val minHeight = maxTop + maxBottom
        if (width > minWidth && height > minHeight) {
            val path = Path()
            //四个角:右上,右下,左下,左上
            path.moveTo(leftTopRadius.toFloat(), 0F)

            path.lineTo((width - rightTopRadius).toFloat() , 0F)
            path.quadTo(width.toFloat(), 0F, width.toFloat(), rightTopRadius.toFloat())

            path.lineTo(width.toFloat(), (height - rightBottomRadius).toFloat())
            path.quadTo(width.toFloat(), height.toFloat(), (width - rightBottomRadius).toFloat(), height.toFloat())

            path.lineTo(leftBottomRadius.toFloat(), height.toFloat())
            path.quadTo(0F, height.toFloat(), 0F, (height - leftBottomRadius).toFloat())

            path.lineTo(0F, leftTopRadius.toFloat())
            path.quadTo(0F, 0F, leftTopRadius.toFloat(), 0F)

            canvas!!.clipPath(path)

            /*val paint = Paint()
            paint.setColor(Color.BLUE)
            paint.style = Paint.Style.STROKE
            paint.strokeWidth = 2f
            canvas!!.drawPath(path, paint)*/
        }
        super.onDraw(canvas)
    }

}

1、当声明了radius属性,并且某个方向的radiusX属性没有声明时, 则使用radius的值替代该放下的radiusX;

2、画布裁切需要在super.onDraw(canvas)之前执行;

3、本程序对裁切进行了一些限制(假如不符合你的需求,你可以去掉这些限制并写上你的限制条件)

限制1:自定义view控件的宽度必须大于(view左半边最大半径和view右半边最大半径之和),即

必须满足条件:

宽度 :view的width > (maxLeft + maxRight)

高度 :同理

//左半边的最大半径
val maxLeft = Math.max(leftTopRadius, leftBottomRadius)
//右半边的最大半径
val maxRight = Math.max(rightTopRadius, rightBottomRadius)

//maxLeft + maxRight 就是view需要满足的最小宽度,同理height

4、创建一个Path路径对象来描述画布应该沿着什么路径进行裁切。执行canvas.clipPath(),之后在canvas上进行的绘制操作就只会在这部分区域进行绘制了。

这里强调一下绘制圆角使用的是贝塞尔曲线(没接触过的话可以参考下贝塞尔曲线简单介绍)。

3、xml中引用自定义view

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center"
        >
        <com.example.helloworld.views.RoundImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:leftTopRadius="70dp"
            app:leftBottomRadius="60dp"
            app:rightTopRadius="25dp"
            app:rightBottomRadius="60dp"
            android:src="@drawable/maps"
            />
</LinearLayout>

原图:

Android 自定义ImageView实现圆角

程序效果:

Android 自定义ImageView实现圆角

 解释一下:

1、可以看到drawable图片的像素值为419 x 418;

2、xml中RoundImageView的宽高都是设置为wrap_content, 这意味着控件的宽高是根据控件内部装载的内容大小来决定的。在onDraw方法中, 已经测量出了RoundImageView的宽高,即为图片的宽高(系统在onMeasure时已经测量出来尺寸)。在xml中设置的四个方向的半径值满足程序的条件,即view的width > (maxLeft + maxRight)===>419 > (70 + 60)x2,这里要乘以2是因为xml使用的是dp作为长度单位,测试机器的1dp=2px,高度同理。 所以会裁切RoundImageView的四个顶角。文章来源地址https://www.toymoban.com/news/detail-427977.html

到了这里,关于Android 自定义ImageView实现圆角的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android开发——控件EditText, 2.获取EditText输入的数据,通过按钮点击实现,ImageView控件,缩放类型,控件ProgressBar,常用属性详解,进度条设置

    1. android : hint 输入提示 2. android : textColorHint  输入提示文字的颜色 3. android : inputType  输入类型 4. android : drawableXxxx 在输入框的指定方位添加图片 5. android : drawablePadding  设置图片与输入内容的间距 6. android : paddingxxxx  设置内容与边框的间距 7. android : backgrou

    2024年02月07日
    浏览(32)
  • Android实现一个带清除和提交按钮的清爽圆角搜索框

    运行效果:   放入Toolbar的效果     清除按钮有内容才显示:  下面是教程: 实现一个圆角搜索框,可以使用 CardView 来实现,同时可以添加一个 EditText 和两个 ImageView 作为清除和提交按钮。 activity_main 其中, EditText 的 background 设置为 @null ,使其没有边框,从而使 CardView 的

    2024年02月02日
    浏览(31)
  • Android入门教程 | ImageView 图片显示

    为了让App界面更美观生动,我们可以放上图片。 显示图片是“刚需”。不论是书籍,报纸,网站,都有显示图片的需求。毕竟“无图无真相”。 在 Android 应用开发中,我们通常使用 ImageView 来显示图片。 ImageView的主要属性 ImageView的使用 ImageView经常用来显示图片。例如直接显

    2024年02月03日
    浏览(47)
  • 【和UI斗智斗勇的日子】Android实现一个只有四个圆角有边框的边框

    如下图所示,这是安卓中最基础的一个边框 它的代码是这样实现的 如果要给它加一个圆角,他会变成这样 实现它的代码也很简单,如下: 依旧很简单对吧,那么如果是下面这样的边框呢 我们只要四个角有边框,这样的边框恐怕无法用上面的 stroke 来实现,那么我们遇到这样

    2023年04月27日
    浏览(63)
  • Android:ImageView xml方式配置selector 图片切换

    1、在 res/drawable 目录下创建一个新的XML文件,比如 selector_image.xml ?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"? selector xmlns:android=\\\"http://schemas.android.com/apk/res/android\\\" !-- 背景选择器 state_pressed  按下 state_focused 获得焦点 默认 图片 --     item android:state_pressed=\\\"true\\\" android:drawable=\\\"@drawable/image_pressed\\\"

    2024年02月15日
    浏览(30)
  • Android终极大招之全面取代drawble文件实现View圆角背景样式的新方案

    最近一直忙于音视频SDK的开发,遇到很多问题,简单来说,就是怎么让别人接入SDK时越简单越好。相信大多数Android开发都会遇到一个场景,给TextView或Button添加背景颜色,修改圆角,描边等需求。一看到这样的实现效果,自然就是创建drawble文件,设置相关属性shap,color,ra

    2024年02月07日
    浏览(30)
  • 一起Talk Android吧(第五百四十回:ImageView的缩放)

    各位看官们大家好,上一回中咱们说的例子是\\\"RxJava中的总结\\\",本章回中介绍的例子是\\\"I mageView的缩放 \\\"。闲话休提,言归正转,让我们一起Talk Android吧! 通常情况下ImageView组件主要用来显示图片,因此需要使用图片当作显示内容,这个可以通过 ImageView 的src属性来设置被显示的

    2023年04月09日
    浏览(32)
  • Android双击图片放大移动图中双击点到ImageView区域中心,Kotlin

      初始化状态,ImageView里面只是显示一张fitcenter被缩放的原图,当手指在图片上双击后(记录双击点位置:mCurX,mCurY)画一个红色小圆圈标记双击位置,放大图片,然后把放大后的图的(原mCurX,mCurY)位置移动到区域中心点位置,用大的红色圆圈标记。   双击:     放大图

    2024年01月21日
    浏览(35)
  • Android LinearLayout dynamic add child ImageView,Glide load,kotlin

    Android LinearLayout dynamic add child ImageView,Glide load,kotlin  images.xml image.xml Android Glide onlyRetrieveFromCache downloadOnly submit ,kotlin_zhangphil的博客-CSDN博客 【代码】Android Paging 3,kotlin(1)在实际的开发中,虽然Glide解决了快速加载图片的问题,但还有一个问题悬而未决:比如用户的头像,

    2024年02月14日
    浏览(30)
  • Kubernetes 笔记(14)— 滚动更新、定义应用版本、实现应用更新、管理应用更新、添加更新描述

    滚动更新,使用 kubectl rollout 实现用户无感知的应用升级和降级。 在 Kubernetes 里,版本更新使用的不是 API 对象,而是两个命令: kubectl apply 和 kubectl rollout ,当然它们也要搭配部署应用所需要的 Deployment 、 DaemonSet 等 YAML 文件。 我们常常会简单地认为“版本”就是应用程序的

    2023年04月19日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包