Android实现圆角控件

Android实现圆角控件

在Android开发过程中,控件的使用是最常见、最基本的。但是我们都知道,在Android中的控件都是矩形的,而在实际项目中,我们的UI设计师经常会使用一些圆角的控件。那么,在Android有哪些方式可以实现圆角控件了,在使用和适配的过程当中,又有哪些问题了。下面,我将介绍Android中常见的实现圆角方式。

自定义方式实现圆角:


androidView.gif

常见实现方式

  1. 使用背景图片
  2. 使用shape方式
  3. 使用CardView控件
  4. 使用ViewOutlineProvider裁剪View
  5. 使用自定义控件
    1. 使用Canvas 的 clipXxx() 系列方法
    2. 通过自定义 Drawable 实现

使用背景图片

有圆角的设计时,让设计师给我们一张圆角背景的切图,然后将圆角切图作为控件的背景设置上去,那么控件在显示时就成圆角了;但是使用这种方式时,不同的圆角大小、四个角中可能并不是都有圆角或者圆角大小不一样时,需要动态修改背景时,都需要使用不同的图片,并且每次调整都需要重新切图和替换,那么设计师的工作量就大了很多,而且apk的体积就会增大很多。所以在实际中基本上不使用这种方式实现圆角,也不推荐使用

使用shape方式

使用shape的方式实现圆角,这应该是我们在平时使用的最多的一种方式了,通过一个xml文件实现,然后直接将这个xml文件作为控件的背景即可。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="5dp"/>
    <solid android:color="#FF0000" />
</shape>

通过以上方式我们就实现了一个背景为红色、四个圆角都为5dp的圆角背景图,然后直接将这个文件作为 android:background 的属性值即可。这种方式在创建和使用的过程都很简单;而且占用的空间也很小,在实际的项目中使用很普遍(shape还有其他的很多属性、包括边框、渐变等)。但是,通过shape的方式实现圆角也有这一些问题,就是对于不同的背景颜色、圆角大小、四个角圆角不一致时,需要定义多个shape文件,而且在有多人开发并且项目没有很好的规范时,可能还会导致同一种背景样式的shape被重复创建;甚至同一个人对于同一种类型的shape都重复创建,从而导致shape文件很多,而且很混乱,不好维护与管理。所以在使用这种方式的时候一定需要有一个规范,并且需要每一个开发者都严格按照规范来。

使用CardView控件

CardView 是在Android5.0推出的一个控件(在使用时需要添加依赖),继承自FrameLayout,可以让我们使用类似卡片布局来显示一致性效果的内容。同时卡片还可以包含圆角和阴影效果。

CardView 控件属性:

app:cardBackgroundColor这是设置背景颜色 
app:cardCornerRadius这是设置圆角大小 
app:cardElevation这是设置z轴的阴影 
app:cardMaxElevation这是设置z轴的最大高度值 
app:cardUseCompatPadding是否使用CompatPadding 
app:cardPreventCornerOverlap是否使用PreventCornerOverlap 
app:contentPadding 设置内容的padding 
app:contentPaddingLeft 设置内容的左padding 
app:contentPaddingTop 设置内容的上padding 
app:contentPaddingRight 设置内容的右padding 
app:contentPaddingBottom 设置内容的底padding

阴影:在Android5.0及以上设置控件阴影可以通过 elevation 属性或者 translationZ属性控制。(elevation 是静态值,是View在Z轴上的初始值;translationZ是动态值,是Z上的偏移变化。Z轴阴影: Z = elevation + translationZ)

使用CardView实现控件圆角,因为CardView继承至FrameLayout,所以作为直接父布局时只能实现相对简单的样式,而如果我们需要实现类似 RelativeLayout 的布局话,那么我们还是只能使用 RelativeLayout ,然后将CardView嵌套在外面;另外直接使用CardView,是无法单独指定某个或两个角是直角,其他是圆角的。

使用ViewOutlineProvider裁剪View

在Android5.0及以上系统,实现圆角我们又多了一种方式,那就是使用 ViewOutlineProvider 的方式,这种方式通过代码指定我们的控件形状,基本用法;

view.setClipToOutline(true);
view.setOutlineProvider(new ViewOutlineProvider() {
    @Override
    public void getOutline(View view, Outline outline) {
        outline.setRoundRect(0,0,view.getWidth(),view.getHeight(),5);
    }
});

通过outline.setRoundRect() 方法,我们将控件设置成圆角, outline 还有其他的方法 setRect()setOval()setConvexPath() 方法指定不同的形状,通过 setConvexPath() 我们还可以指定一个凸路径(ConvexPath 这里简单理解为 圆角矩形的圆角度数大于矩形的高度或宽度(上下圆角度数的边长和大于高度或者左右圆角度数的边长大于高度,那么就不是 ConvexPath 了))。在Android5.0以上使用这种方式实现圆角也是可以的。但是使用这种方式也有一些缺点,就是必须是Android5.0以上系统,另外一点就是需要在代码中进行设置,不能在xml文件中指定。

使用自定义控件

通过自定义控件的方式实现圆角或者其他的形状,使用这种方式灵活性高,没有版本限制。但是他最为明显的缺点就是需要自己实现自定义控件,起初阶段比较麻烦。而通过自定义控件实现也有多种方式,这里我主要介绍两种:裁剪画布通过自定义Drawable作为控件背景形式

  • 使用Canvas 的 clipXxx() 系列方法

    通过 Canvas 的 canvas.clipRect()canvas.clipPath() 等系列方法对画布进行裁剪来实现圆角控件,大家都知道Android控件显示都是通过画布(Canvas)来呈现的,那么我们直接把画布裁剪掉了,自然绘制在画布上的内容也就被裁剪掉了,而画布被裁剪成什么形状了,最终显示的肯定也就是这种形状。

      @Override
      public void draw(Canvas canvas) {
          canvas.clipRect(rectF);
          super.draw(canvas);
      }
    

    使用这种方式有一个问题,那就是锯齿比较明显,我们都知道在使用画笔进行绘制的时候,都会这是画笔的抗锯齿效果,但是canvas的clip系列方法并没有这个功能,这就导致了我们通过这种方式实现自定义的圆角锯齿效果比较明显。对界面要求比较高的话,可能会不能通过。

  • 通过自定义 Drawable 实现

    既然通过直接裁剪画布有锯齿效果,而我们上面说过通过shape的方式实现是比较常见的,而且是有很好的抗锯齿效果,但是需要创建多个shape文件实现不同的圆角和颜色。那么,我们能不能将创建shape的过程通过代码的形式创建,然后在自定义控件中进行使用,并且将圆角参数、颜色参数、边框参数通过自定义控件的属性进行定义了。这样一来,我们就既省去了需要创建多个shape文件的问题,也解决了锯齿的问题。我们通过自定义Drawable的方式,对自定义的属性通过画笔、路径等形式绘制到自定的Drawable中,然后将自定义的Drawable作为控件的背景就实现了这个功能。自定义Drawable代码,通过自定义Drawable实现的可指定圆角大小、边框属性的RadiusFrameLayout点击查看更多圆角控件

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,175评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,674评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,151评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,597评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,505评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,969评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,455评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,118评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,227评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,213评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,214评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,928评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,512评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,616评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,848评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,228评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,772评论 2 339

推荐阅读更多精彩内容