文档管理中心

圆角边框问题

问题现象

borderRadius属性可以为组件设置边框的圆角半径,但某些场景下直接设置borderRadius属性可能会导致圆角不生效或显示异常。如何根据不同问题场景正确设置圆角边框?

展开

场景

场景说明

场景一:直接设置borderRadius属性圆角不生效

部分组件和自定义组件直接设置borderRadius无法成功设置圆角

场景二:同时设置border属性和borderRadius属性圆角不生效

先设置borderRadius后设置border时无法成功设置圆角

场景三:不同背景色重叠导致圆角出现黑边

父子组件或存在重叠的兄弟组件如果背景色不同,圆角处会出现黑边。

背景知识

  • borderRadius:设置边框的圆角半径。圆角大小受组件尺寸限制,最大值为组件宽或高的一半。
  • clip:是否对子组件超出当前组件范围外的区域进行裁剪。

解决方案

  • 场景一:直接设置borderRadius属性圆角不生效。

    示例一:地图组件MapComponent直接设置borderRadius属性圆角不生效。

    示例二:@Component自定义组件直接设置borderRadius属性圆角不生效。

    大多数情况下,直接给组件设置borderRadius即可实现圆角边框,但部分类似于地图组件这样渲染较为复杂的组件和所有的自定义组件,需要在设置borderRadius的同时添加clip属性才能实现圆角边框,示例代码如下:

    收起
    自动换行
    深色代码主题
    复制
    1. import { MapComponent, mapCommon, map } from '@kit.MapKit';
    2. import { AsyncCallback } from '@kit.BasicServicesKit';
    3. @Entry
    4. @Component
    5. struct Index {
    6. private TAG = 'MapDemo';
    7. private mapOptions?: mapCommon.MapOptions;
    8. private callback?: AsyncCallback<map.MapComponentController>;
    9. private mapController?: map.MapComponentController;
    10. private mapEventManager?: map.MapEventManager;
    11. aboutToAppear(): void {
    12. // 地图初始化参数,设置地图中心点坐标及层级
    13. this.mapOptions = {
    14. position: {
    15. target: {
    16. latitude: 39.9,
    17. longitude: 116.4
    18. },
    19. zoom: 10
    20. }
    21. };
    22. // 地图初始化的回调
    23. this.callback = async (err, mapController) => {
    24. if (!err) {
    25. // 获取地图的控制器类,用来操作地图
    26. this.mapController = mapController;
    27. this.mapEventManager = this.mapController.getEventManager();
    28. let callback = () => {
    29. console.info(this.TAG, `on-mapLoad`);
    30. };
    31. this.mapEventManager.on('mapLoad', callback);
    32. }
    33. };
    34. }
    35. build() {
    36. Column() {
    37. // 调用MapComponent组件初始化地图
    38. MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
    39. .width(200)
    40. .height(200)
    41. .borderRadius(50)
    42. .clip(true);
    43. TestColumn()
    44. .width(200)
    45. .height(200)
    46. .borderRadius(50)
    47. .clip(true);
    48. }
    49. .justifyContent(FlexAlign.SpaceEvenly)
    50. .width('100%')
    51. .height('100%');
    52. }
    53. }
    54. @Component
    55. struct TestColumn {
    56. build() {
    57. Column()
    58. .width('100%')
    59. .height('100%')
    60. .backgroundColor('#E5E5EA');
    61. }
    62. }

    效果图如下:

  • 场景二:同时设置border属性和borderRadius属性圆角不生效。

    border设置在borderRadius之后会导致border覆盖borderRadius,并且,border已经存在参数radius用于控制圆角。如果border属性的radius参数缺省,需要borderRadius设置在border后。

    示例代码如下:

    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Index3 {
    4. build() {
    5. Column() {
    6. Button('按钮')
    7. .type(ButtonType.Normal)
    8. .border({ color: '#E5E7EB', width: 1 }) // 调整该属性配置顺序在borderRadius前
    9. .borderRadius(16) // 设置borderRadius生效
    10. .backgroundColor(0x317aff)
    11. .fontColor('white')
    12. .width(108)
    13. .height(60)
    14. .fontSize(28)
    15. .margin({ right: 12 })
    16. .padding(0);
    17. }
    18. .justifyContent(FlexAlign.Center)
    19. .alignItems(HorizontalAlign.Center)
    20. .height('100%')
    21. .width('100%');
    22. }
    23. }

    效果图如下:

  • 场景三:不同背景色重叠导致圆角出现黑边。

    示例一:Video组件与父容器Column背景色不同时,四角出现黑边。

    问题现象图如下:

    由于抗锯齿是半透明像素(GPU绘制正常原理),导致无法完全遮挡下方内容。需要将两者背景色统一或者将Video组件的背景色设为透明。

    示例代码如下:

    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Index2 {
    4. @State videoSrc: ResourceStr = $r('app.media.input');
    5. @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X;
    6. isAutoPlay: boolean = true;
    7. showControls: boolean = true;
    8. controller: VideoController = new VideoController();
    9. build() {
    10. Column() {
    11. Video({
    12. src: this.videoSrc,
    13. currentProgressRate: this.curRate,
    14. controller: this.controller
    15. })
    16. .width(300)
    17. .height(600)
    18. .borderRadius(8)
    19. .backgroundColor(Color.Transparent) // 设置背景色为透明(或与父组件背景一直),防止圆角边框出现
    20. .autoPlay(this.isAutoPlay)
    21. .controls(this.showControls);
    22. }
    23. .width('100%')
    24. .height('100%')
    25. .justifyContent(FlexAlign.Center)
    26. // 或者添加父组件背景,要求与video组件背景一致,防止圆角边框出现
    27. .backgroundColor('#fff');
    28. }
    29. }

    效果图如下:

    示例二:存在重叠关系的兄弟组件背景色不同时,四角出现黑边。

    问题代码如下:

    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Index4 {
    4. build() {
    5. Stack({ alignContent: Alignment.TopStart }) {
    6. Column() {
    7. }
    8. .backgroundColor(Color.Black)
    9. .width('100%')
    10. .height('100%');
    11. Column() {
    12. }
    13. .backgroundColor('#ffe5e3e3')
    14. .backgroundColor(Color.White)
    15. .width('100%')
    16. .height('100%');
    17. }
    18. .margin({ left: 50, top: 50 })
    19. .width(300)
    20. .height(300)
    21. .clip(true)
    22. .borderRadius(30);
    23. }
    24. }

    方法一:同示例一解决方法,需要将两者背景色统一。

    方法二:令上层组件的圆角半径小于下层组件的圆角半径以覆盖原本重叠的边缘区域。

    示例代码如下:

    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Index5 {
    4. build() {
    5. Stack({ alignContent: Alignment.TopStart }) {
    6. Column() {
    7. }
    8. .borderRadius(30)
    9. .backgroundColor(Color.Black)
    10. .width('100%')
    11. .height('100%');
    12. Column() {
    13. }
    14. .borderRadius(25)
    15. .backgroundColor(Color.White)
    16. .width('100%')
    17. .height('100%');
    18. }
    19. .margin({ left: 50, top: 50 })
    20. .width(300)
    21. .height(300);
    22. }
    23. }

    方法三:缩小被遮盖的下层组件尺寸,防止边缘区域重合。

    示例代码如下:

    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Index6 {
    4. build() {
    5. Stack({ alignContent: Alignment.Center }) {
    6. Column() {
    7. }
    8. .borderRadius(30)
    9. .backgroundColor(Color.Black)
    10. .width('298px')
    11. .height('298px');
    12. Column() {
    13. }
    14. .borderRadius(30)
    15. .backgroundColor(Color.White)
    16. .width('300px')
    17. .height('300px');
    18. }
    19. .width(300)
    20. .height(300);
    21. }
    22. }

    效果图如下: