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的层级来实现,不过写代码,也可以实现更多的需求


相关文章
|
1月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
80 0
|
14天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
16天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
28 5
|
24天前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
23天前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
30 2
|
25天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
28天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
24 2
|
1月前
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
35 3
|
1月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
3月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
116 3