Android 实现圆弧背景(Shape实现和自定义View)

简介: 如今Android系统的App,很多时候为了有更好的用户体验,都会有各种好看的UI,动画,点击效果等等,其中圆弧的控件在App中很常见,今儿就自己总结下自己实现圆弧的两种基础的方法。即Shape方法和使用View里面的方法自己画。

一、背景


如今Android系统的App,很多时候为了有更好的用户体验,都会有各种好看的UI,动画,点击效果等等,其中圆弧的控件在App中很常见,今儿就自己总结下自己实现圆弧的两种基础的方法。即Shape方法和使用View里面的方法自己画。


二、Shape属性


shape:即形状的意思,这是一种在 xml文件中定义的通用形状。


文件位置:res / drawable / 文件名.xml


代码:一个TextView的背景


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <padding
        android:bottom="8dp"
        android:left="24dp"
        android:right="24dp"
        android:top="8dp"/>
    <solid android:color="#ef7300" />
    <corners android:radius="12dp" />
</shape>

展示:

0c9b6ff1120a893bb8978f84398ddef.png



这样实现起来非常简单!但是需求有时候又很离谱,我们开发又必须做,这时候就得老老实实代码去实现。


关于Shape的属性介绍:可以看

Android shape的用法详解_&岁月不待人&的博客-CSDN博客_android shape

一、什么是Shape属性在项目中经常会给控件定义背景,有时候有些界面可以叫UI做好,但如何显示的更加的贴近用户,则需要我们客户端去优化。如果在设置背景Android:background=“图片、颜色”,设置单一的属性并不能带来更好的体验。我们此时就可以使用shape属性作为控件的背景。shape怎么弄?1. 在res/drawable下新建一个xml文件;2. 在代码中引用这个xml文件,引用方式和图片一样。shape有哪些功能?corners ———-圆角gradi

https://blog.csdn.net/LoveFHM/article/details/109508798


三、使用ViewGroup的onDraw或者dispatchDraw实现自定义View


需求:IM的聊天气泡绘制,1、指定的位置的弧度角,2、当为群主时,会给聊天气泡加上金边。


实现原理:众所周知,View是Android所有控件的基类,常用的TextView和ImageView是继承自VIew。ViewGroup是View的组合,它可以包含很多View以及ViewGroup,所以可以直接重写onDraw或者dispatchDraw来自定义View。主要就是使用canvas,paint,path这些东西来实现。


核心代码:


 

private fun drawBackGround(context: Context, canvas: Canvas, data: ImMsgIn, width: Int, height: Int, chatType: Int) {
        val mBgColorOrigin = ContextCompat.getColor(context, R.color.im_msg_bg_origin)
        isSelfMessage = data.getSelfUserId() == data.getSenderId()//是自己的消息
        isOwner = data.getSenderId() == data.getOwnerId()//是否是群主
        val path = Path()
        paint.strokeWidth = 1f
        paint.style = Paint.Style.FILL
        paint.color = setColor(context, data, chatType)
        if (isSelfMessage) { //发送者为自己,统一为圆弧背景,无金边
            val rectF = RectF(0f, 0f, width.toFloat(), height.toFloat())
            val radii = floatArrayOf(dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 0f), dpToPx(context, 0f), dpToPx(context, 8f), dpToPx(context, 8f))//右下为直角,其他角弧度为8
            path.addRoundRect(rectF, radii, Path.Direction.CW)
            canvas.drawPath(path, paint)
        } else {
            paint.style = Paint.Style.FILL
            val rectF = RectF(0f, 0f, width.toFloat(), height.toFloat())
            val radii = floatArrayOf(dpToPx(context, 0f), dpToPx(context, 0f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f))
            path.addRoundRect(rectF, radii, Path.Direction.CW)
            canvas.drawPath(path, paint)
            isOwnerReplyQuestionIsPublic = true
            if (data.getReplyMsgQuestionIsPublished() != null) isOwnerReplyQuestionIsPublic = data.getReplyMsgQuestionIsPublished() == true
            if (isOwner && (isOwnerReplyQuestionIsPublic || chatType == UiMsgType.PRIVATE_CHAT)) {
                paint.strokeWidth = 1f
                paint.color = mBgColorOrigin
                paint.style = Paint.Style.STROKE //画金色边框
                canvas.drawPath(drawRect(context, width, height), paint)
            } else if (data.getUiTypeWithMessageType() == UiMsgType.MSG_TYPE_QUESTION && data.getQuestionStatus() == 0 && data.getPublished()) {
                paint.strokeWidth = 1f
                paint.color = mBgColorOrigin
                paint.style = Paint.Style.STROKE
                canvas.drawPath(drawRect(context, width, height), paint)
            }
        }
    }
  //金色边框
    private fun drawRect(context: Context, width: Int, height: Int): Path {
        val path = Path()
        val rectF = RectF(0.5f, 0.5f, width.toFloat() - 0.5f, height.toFloat() - 0.5f)
        val radii = floatArrayOf(dpToPx(context, 0f), dpToPx(context, 0f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f), dpToPx(context, 8f))
        path.addRoundRect(rectF, radii, Path.Direction.CW)
        return path
    }
    private fun dpToPx(context: Context, dipValue: Float): Float {
        val scale = context.applicationContext.resources.displayMetrics.density
        return dipValue * scale + 0.5f
    }

其实,这个金边吧,其实也可以通过xml文件里叠加View的层级来实现,不过写代码,也可以实现更多的需求


相关文章
|
6月前
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
518 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
6月前
|
Android开发
Android自定义view之利用PathEffect实现动态效果
本文介绍如何在Android自定义View中利用`PathEffect`实现动态效果。通过改变偏移量,结合`PathEffect`的子类(如`CornerPathEffect`、`DashPathEffect`、`PathDashPathEffect`等)实现路径绘制的动态变化。文章详细解析了各子类的功能与参数,并通过案例代码展示了如何使用`ComposePathEffect`组合效果,以及通过修改偏移量实现动画。最终效果为一个菱形图案沿路径运动,源码附于文末供参考。
115 0
|
6月前
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
322 65
Android自定义view之网易云推荐歌单界面
|
6月前
|
XML 前端开发 Android开发
一篇文章带你走近Android自定义view
这是一篇关于Android自定义View的全面教程,涵盖从基础到进阶的知识点。文章首先讲解了自定义View的必要性及简单实现(如通过三个构造函数解决焦点问题),接着深入探讨Canvas绘图、自定义属性设置、动画实现等内容。还提供了具体案例,如跑马灯、折线图、太极图等。此外,文章详细解析了View绘制流程(measure、layout、draw)和事件分发机制。最后延伸至SurfaceView、GLSurfaceView、SVG动画等高级主题,并附带GitHub案例供实践。适合希望深入理解Android自定义View的开发者学习参考。
667 84
|
6月前
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
188 3
|
6月前
|
Android开发 开发者
Android自定义view之围棋动画(化繁为简)
本文介绍了Android自定义View的动画实现,通过两个案例拓展动态效果。第一个案例基于`drawArc`方法实现单次动画,借助布尔值控制动画流程。第二个案例以围棋动画为例,从简单的小球直线运动到双向变速运动,最终实现循环动画效果。代码结构清晰,逻辑简明,展示了如何化繁为简实现复杂动画,帮助读者拓展动态效果设计思路。文末提供完整源码,适合初学者和进阶开发者学习参考。
127 0
Android自定义view之围棋动画(化繁为简)
|
6月前
|
Java Android开发 开发者
Android自定义view之围棋动画
本文详细介绍了在Android中自定义View实现围棋动画的过程。从测量宽高、绘制棋盘背景,到创建固定棋子及动态棋子,最后通过属性动画实现棋子的移动效果。文章还讲解了如何通过自定义属性调整棋子和棋盘的颜色及动画时长,并优化视觉效果,如添加渐变色让白子更明显。最终效果既可作为围棋动画展示,也可用作加载等待动画。代码完整,适合进阶开发者学习参考。
148 0
|
Android开发 数据格式 XML
Android项目实战(三十六):给背景加上阴影效果
原文:Android项目实战(三十六):给背景加上阴影效果   圆角背景大家应该经常用: 一个drawable资源文件  里面控制corner圆角 和solid填充色     那么在此基础上 , 实现带阴影效果的圆角背景    代码如下  效果: 可以看到 右侧和下侧都有一个小范围的灰色阴影效果。
1873 2
|
Android开发 数据格式 XML
Android项目实战(三十六):给背景加上阴影效果
圆角背景大家应该经常用: 一个drawable资源文件  里面控制corner圆角 和solid填充色     那么在此基础上 , 实现带阴影效果的圆角背景    代码如下  效果: 可以看到 右侧和下侧都有一个小范围的灰色阴影效果。
1302 0
|
1月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
238 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
下一篇
oss云网关配置