{"id":13605492,"url":"https://github.com/Devlight/CornerCutLinearLayout","last_synced_at":"2025-04-12T05:33:27.301Z","repository":{"id":56255357,"uuid":"250202175","full_name":"Devlight/CornerCutLinearLayout","owner":"Devlight","description":"Linear Layout that allow corner (parent and children) cuts, complex shadow and divider.","archived":false,"fork":false,"pushed_at":"2021-01-25T13:15:00.000Z","size":8240,"stargazers_count":453,"open_issues_count":1,"forks_count":27,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-11-06T17:07:32.908Z","etag":null,"topics":["android","android-library","android-ui","kotlin","kotlin-android","kotlin-library","library","ui"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Devlight.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-26T08:31:49.000Z","updated_at":"2024-10-25T13:52:43.000Z","dependencies_parsed_at":"2022-08-15T15:31:21.667Z","dependency_job_id":null,"html_url":"https://github.com/Devlight/CornerCutLinearLayout","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devlight%2FCornerCutLinearLayout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devlight%2FCornerCutLinearLayout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devlight%2FCornerCutLinearLayout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Devlight%2FCornerCutLinearLayout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Devlight","download_url":"https://codeload.github.com/Devlight/CornerCutLinearLayout/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223497894,"owners_count":17155215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","android-ui","kotlin","kotlin-android","kotlin-library","library","ui"],"created_at":"2024-08-01T19:00:59.355Z","updated_at":"2024-11-07T10:30:43.822Z","avatar_url":"https://github.com/Devlight.png","language":"Kotlin","readme":"# CornerCutLinearLayout\n\n[![](https://jitpack.io/v/Devlight/CornerCutLinearLayout.svg)](https://jitpack.io/#Devlight/CornerCutLinearLayout) [![Android Arsenal]( https://img.shields.io/badge/Android%20Arsenal-CornerCutLinearLayout-green.svg?style=flat )]( https://android-arsenal.com/details/1/8111 )\n\n`CornerCutLinearLayout` extends [`LinearLayout`](https://developer.android.com/reference/android/widget/LinearLayout). It allows cutting parent corners with different shapes and build proper shadow for complex shapes.\\\nIt also allows cutting each child's corners.\n\nDeveloped by [Devlight](https://www.devlight.io/) company.  \n\n\u003cp align=\"center\"\u003e\u003cimg src=\"/assets/images/logo.png\" width=\"200\" height=\"auto\" align=\"center\"\u003e\u003cimg src=\"/assets/images/devlight_logo.png\" height=\"100\" width=\"auto\" align=\"center\" hspace=\"16\"\u003e\u003c/p\u003e\n\nAdditionally, using available properties and custom providers, those cuts may be turned into cutouts of different shapes, sizes, etc.\\\nWidget's sole purpose is to use with children with no transformations (like rotation, scale, matrix transformations).\n\nAmongst additional features:\n- RTL support\n- child layout parameters that allow overriding default parent parameters\n- custom shadow\n- custom dividers \u0026 providers\n- custom cutouts \u0026 providers\n- custom view visible area provider\n\n# Installation\n\n**Step 1.**  Add the JitPack repository to your project's `build.gradle` file:\n\n```groovy\nallprojects {\n    repositories {\n        ...\n        maven { url 'https://jitpack.io' }\n    }\n}\n```\n\nor\n\n```groovy\nsubprojects { \n    repositories {\n        ...\n        maven {\n            ...\n            url = \"https://jitpack.io\"\n        }\n    }\n}\n```\n\n**Step 2.**  Add the following dependency to your target module's `build.gradle` file:\n\n```groovy\ndependencies {\n    implementation 'com.github.Devlight:CornerCutLinearLayout:1.0.5'\n}\n```\n\n# Usage\n\nFor simple quick usage that covers most use cases, see **Basics** section below.\\\nFor more complex usage section **Advanced** might be useful.\n\n# Basics\n\n#### Declaration in XML\n\nAll widget attributes start with `ccll_` prefix. Children's layout attributes starts with `layout_ccll_` prefix, respectively. There are plenty of attributes. In order to facilitate their usage, they separated into few categories with start prefix:\n- `ccll_` or `ccll_corner_cut` - global widget attributes\n- `ccll_child_` - global child cut attributes\n- `ccll_custom_shadow` - custom shadow attributes\n- `ccll_custom_divider` - custom divider attributes\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    android:id=\"@+id/ccll_kotlin_synthetic_view\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"#FFFFFF\"\n    android:orientation=\"vertical\"\n\n    app:ccll_corner_cut_flag=\"start_top|end_bottom\"\n    app:ccll_corner_cut_size=\"24dp\"\n    app:ccll_corner_cut_type=\"oval\"\n\n    app:ccll_child_corner_cut_type=\"oval_inverse\"\n\n    app:ccll_custom_shadow_color=\"#FEB545\"\n    app:ccll_custom_shadow_radius=\"16dp\"\u003e\n\n    \u003cView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"50dp\" /\u003e\n\n    \u003cView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"50dp\" /\u003e\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n#### Declaration in Code (Kotlin)\n\nAll XML attributes correspond to `CornerCutLinearLayout`'s property or function.\n\n```kotlin\nwith(ccll_kotlin_synthetic_view) {\n    val density = resources.displayMetrics.density\n    cornerCutFlag = combineFlags(CornerCutFlag.START_TOP, CornerCutFlag.END_BOTTOM)\n    setCornerCutSize(density * 24)\n    setCornerCutType(CornerCutType.OVAL)\n    setChildCornerCutType(CornerCutType.OVAL_INVERSE)\n    customShadowColor = Color.parseColor(\"#FEB545\")\n    customShadowRadius = density * 16\n}\n```\nVisual result would be follow:\n\n\u003cimg src=\"/assets/images/first_usage.jpg\" width=\"150\" height=\"150\"\u003e\n\n### Corner Cut Anatomy\n\nBy default `CornerCutType.OVAL` is used for both parent corner and child cuts. Corner cut are bounded to its personal dimensions - **depth** and **length**.\n\n**Depth** - relative to orientation width of the cutout bounds.\\\n**Length** - relative to orientation height of the cutout bounds.\n\nEach of 4 parent corner cuts dimensions could be specified individually.\\\nChildren's corner cuts could have separate dimensions for `ChildSideCutFlag.START` and `ChildSideCutFlag.END` sides. Children's corner cuts could also be rotated. The rotation angle could optionally be mirrored.\n\n\u003cimg src=\"/assets/images/anatomy.png\" width=\"420\" height=\"150\"\u003e\n\nAs you may notice, parent corner cuts are purely bounded to corners, but child corner cut bounds are \"mirrored\". Indeed, each child corner cut forms a mirrored path. This strategy was chosen in order for children could separately override the contact part of the corner cut.  \n\nAlso, note that **depth** and **length** depends on widget's layout direction (`LinearLayout.LAYOUT_DIRECTION_LTR` or `LinearLayout.LAYOUT_DIRECTION_RTL`) and orientation (`LinearLayout.VERTICAL` or `LinearLayout.HORIZONTAL`).\n\n### Corner Cut Types\n\nThere are 5 default corner cut types for parent and children corners\\*.\n\n1) Oval.\n\n\u003cimg src=\"/assets/images/oval.jpg\" width=\"150\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_oval.jpg\" width=\"300\" height=\"150\"\u003e\n\n2) Oval Inverse.\n\n\u003cimg src=\"/assets/images/oval_inverse.jpg\" width=\"150\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_oval_inverse.jpg\" width=\"300\" height=\"150\"\u003e\n\n3) Rectangle.\\*\\*\n\n\u003cimg src=\"/assets/images/rectangle.jpg\" width=\"300\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_rectangle.jpg\" width=\"300\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_rectangle_corners.jpg\" width=\"300\" height=\"150\"\u003e\n\n4) Rectangle Inverse.\\*\\*\n\n\u003cimg src=\"/assets/images/rectangle_inverse.jpg\" width=\"300\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_rectangle_inverse.jpg\" width=\"300\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_rectangle_inverse_corners.jpg\" width=\"300\" height=\"150\"\u003e\n\n5) Bevel.\n\n\u003cimg src=\"/assets/images/bevel.jpg\" width=\"150\" height=\"150\"\u003e\u003cimg src=\"/assets/images/child_bevel.jpg\" width=\"300\" height=\"150\"\u003e\n\n\u003e\\* - Each child corner type, in fact, is mirrored and combined into a path from the respective corner cut types of contact children.\\\n\\*\\* - Rectangle types support an internal corner radius. There are respective attributes and view properties for both parent and child cuts.\n\n### Layout Parameters\n\nEach child can override parent defined properties and attributes related to the corner cuts.\n\nIn the examples below, parent `CornerCutLinearLayout` has `ccll_child_corner_cut_type` = `oval_inverse` and the middle children override each corner (different types) \n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    app:ccll_child_corner_cut_type=\"oval_inverse\"\u003e\n    ...\n    \u003cView\n        ...\n        app:layout_ccll_start_top_corner_cut_type=\"oval\"\n        app:layout_ccll_end_top_corner_cut_type=\"bevel\"\n        app:layout_ccll_end_bottom_corner_cut_type=\"rectangle\"\n        app:layout_ccll_start_bottom_corner_cut_type=\"rectangle_inverse\"/\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n\u003cimg src=\"/assets/images/child_override_corner_cut_type.jpg\" width=\"300\" height=\"150\"\u003e\n\n#### Edge Child\nThere also special layout params for the first and last child. For example in a vertical orientation, when the top and bottom children are not aligned to parent top and bottom respectively they can override **contact cut\\*** with the parent.\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    android:gravity=\"center\"\n    app:ccll_child_corner_cut_type=\"oval_inverse\"\u003e\n    \u003cView\n        ...\n        app:layout_ccll_edge_child_parent_contact_corner_cut_type=\"oval\"/\u003e\n        ...\n    \u003cView\n        ...\n        app:layout_ccll_edge_child_parent_contact_corner_cut_type=\"rectangle_inverse\"/\u003e\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n\u003cimg src=\"/assets/images/edge_child_override_contact.jpg\" width=\"300\" height=\"150\"\u003e\n\n\nIn case edge child is aligned to the respective side, they could optionally override parent corner cut type\\*\\*.\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    app:ccll_corner_cut_type=\"bevel\"\u003e\n    \u003cView\n        ...\n        app:layout_ccll_start_top_corner_cut_type=\"oval\"\n        app:layout_ccll_end_top_corner_cut_type=\"rectangle\"\n        app:layout_ccll_edge_child_could_override_parent_corner_cut_type_if_edge_aligned=\"true\"/\u003e\n        ...\n    \u003cView\n        ...\n        app:layout_ccll_start_bottom_corner_cut_type=\"rectangle_inverse\"\n        app:layout_ccll_edge_child_could_override_parent_corner_cut_type_if_edge_aligned=\"true\"/\u003e\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n\u003cimg src=\"/assets/images/edge_child_aligned_override_parent_corners.jpg\" width=\"150\" height=\"150\"\u003e\n\n\n\u003e\\* - By default specified `ccll_child_corner_cut_type` is used for child-parent contact if not overridden by edge child.\\\n\\*\\* - Note that only type of parent corner cut type is overridden, while other properties (depth, length, etc.) are stay preserved.\n\n### Extra Child Corner Cut Properties\n\nThere are next extra child corner cut properties:\n- Depth \u0026 Length Offset\n- Corner Cut Rotation\n\n#### Depth \u0026 Length Offset\n\nEach side of child corner cuts could have different depth and length offset (see anatomy above).\n\n**Example 1 - Depth Offset**\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    app:ccll_child_corner_cut_depth_offset=\"@dimen/offset_24\"\n    app:ccll_child_corner_cut_type=\"oval_inverse\"\u003e\n    ...\n    \u003cView\n        ...\n        app:layout_ccll_end_bottom_corner_cut_type=\"oval\"\n        app:layout_ccll_end_top_corner_cut_type=\"rectangle_inverse\"\n        app:layout_ccll_start_bottom_corner_cut_type=\"bevel\"\n        app:layout_ccll_start_top_corner_cut_type=\"rectangle\" /\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\u003cimg src=\"/assets/images/child_property_offset.png\" width=\"150\" height=\"150\"\u003e\n\n**Example 2 - Depth \u0026 Length Offset**\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    app:ccll_child_corner_cut_type=\"bevel\"\n    app:ccll_child_end_side_corner_cut_depth_offset=\"@dimen/depth_offset\"\n    app:ccll_child_start_side_corner_cut_length_offset=\"@dimen/length_offset\"\n    app:ccll_corner_cut_type=\"bevel\"\u003e\n    \u003cView\n        ...\n        android:layout_marginTop=\"@dimen/offset_8\"\n        android:layout_marginBottom=\"@dimen/offset_8\"/\u003e\n    \u003cView\n        ...\n        android:layout_marginTop=\"@dimen/offset_8\"\n        android:layout_marginBottom=\"@dimen/offset_8\"/\u003e\n\n    \u003cView\n        ...\n        android:layout_marginTop=\"@dimen/offset_8\"\n        android:layout_marginBottom=\"@dimen/offset_8\"/\u003e\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n\u003cimg src=\"/assets/images/child_property_offset_depth_and_length.png\" width=\"150\" height=\"auto\"\u003e\n\n#### Rotation\nEach side could have its corner cuts rotated be specified degree.\nCorresponding attributes are:\n- `ccll_child_start_side_corner_cut_rotation_degree`\n- `ccll_child_end_side_corner_cut_rotation_degree`\n\nAlso, it might be necessary to keep the same mirrored corner cut angle for the both sides. For such purposes attribute `ccll_is_child_corner_cut_end_rotation_mirrored_from_start_rotation` might be helpful.\n\nEach attribute has its corresponding `CornerCutLinearLayout`'s property and/or convenience function.\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    app:ccll_child_corner_cut_type=\"oval\"\n    app:ccll_child_end_side_corner_cut_type=\"oval_inverse\"\n    app:ccll_child_end_side_corner_cut_rotation_degree=\"60\"\n    app:ccll_child_start_side_corner_cut_rotation_degree=\"45\"\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n\u003cimg src=\"/assets/images/child_property_rotation.png\" width=\"150\" height=\"150\"\u003e\n\n### Shadow \nOne of the main problem of [Android's shadow](https://developer.android.com/training/material/shadows-clipping) is that path must be [convex](https://developer.android.com/reference/android/graphics/Path#isConvex()). \n\n\u003e\\* - A path is convex if it has a single contour, and only ever curves in a single direction.\n\nThis widget allows bypass this limitation by automatically building complex shadow (event with cutouts). Of course, shadow is custom and has its pros and cons.\n\n**Pros**:\n- Shadow has custom properties, such as offset \u0026 color (ARGB).\n- Supports complex non convex path.\n\n**Cons**: \n- Shadow is artificial compared to native elevation shadow's nature. Thus, you cannot rely on global source an light position and elevation parameter. \n- Shadow uses view's area (padding), which you should keep in mind during layout process or dynamic change of shadow radius.\n- Shadow does NOT depend on view's or children's background and their transparencies, thus cannot be a composite shadow with the overlays of different levels of transparency (opacity). \n\nBy default shadow are build upon parent padded area combined with all cutouts data. It means that shadow does NOT depend on view's background, child presence or child's background. But this behavior could be changed by `CustomViewAreaProvider` (see **Advanced** section). \n\n**Shadow Padding**.\\\nYou could also enable custom shadow auto padding (`ccll_is_custom_shadow_auto_padding_enabled`), allow or prevent custom shadow over user defined padding. (`ccll_could_draw_custom_shadow_over_user_defined_padding`). Last attribute works only in conjunction with enabled first attribute.\n\nExamples:\n\n\u003cimg src=\"/assets/images/shadow_no_children.jpg\" width=\"150\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/shadow_children.jpg\" width=\"150\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/shadow_no_children_semi_tranparent_bg.jpg\" width=\"150\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/shadow_children_single_bg.jpg\" width=\"150\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/shadow_view_transformation.jpg\" width=\"150\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/shadow_offset.jpg\" width=\"150\" height=\"auto\"\u003e\n\n### Custom Divider\nCustom Divider has similar anatomy and properties as default's LinearLayout divider.\nCustom dividers does not change view's dimension unlike  default's LinearLayout divider did (last adds space at specified by flag position equal to divider's width or height). Custom diviers are drown over view and default dividers. You can combine default and custom divider.\n\nCustom dividers have several advantages though:\n- additional show flags\n- line caps (ROUND, BUTT, SQUARE)\n- seperate start an end padding\n- dashed line divider (width and gap)\n- gravity of dashed divider (`CustomDividerGravity`: `START`, `CENTER`, `END`)\n- custom divider provider (see **Advanced** section)\n\n**Show Flags** (`CustomDividerShowFlag`):\n- `container_beginning` - at view beginning\n- `beginning` - between contact of first view's margin and parent.\n- `middle` - between children contact margins\n- `end` - between contact of last view's margin and parent.\n- `container_end` - at view end\n\n\u003eBy default custom dividers are not taken into consideration when shadow are build. \n\nCustom Divider attributes:\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    app:ccll_custom_divider_color=\"@color/divider\"\n    app:ccll_custom_divider_dash_gap=\"@dimen/divider_dash_gap\"\n    app:ccll_custom_divider_dash_width=\"@dimen/divider_dash_width\"\n    app:ccll_custom_divider_height=\"@dimen/divider_height\"\n    app:ccll_custom_divider_line_cap=\"butt\"\n    app:ccll_custom_divider_show_flag=\"middle|container_end\"\n    app:ccll_custom_divider_gravity=\"center\"\n    app:ccll_custom_divider_padding=\"@dimen/divider_padding\"\n    app:ccll_custom_divider_padding_start=\"@dimen/divider_padding_start\"\n    app:ccll_custom_divider_padding_end=\"@dimen/divider_padding_end\"\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\nExamples:\n\n\u003cimg src=\"/assets/images/divider_example_1.jpg\" width=\"300\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/divider_example_2.jpg\" width=\"300\" height=\"auto\"\u003e\u003cimg src=\"/assets/images/divider_example_3.jpg\" width=\"300\" height=\"auto\"\u003e\n\n# Advanced\nSometimes you might want to have even more complex visible area, divider, cutouts, etc.\nFor such purposes there are custom providers for aforementioned subjects. All of them could be specified programatically. For your convenience, there are also a Kotlin lambda-style functions for the most of the providers.\n\n### Corner Cut Provider\n`CornerCutProvider` allows to override each of 4 widget's corners.\\\nLet's look at an examples.\n\n**Example 1**.\n\n1. As usual define our view at xml (this scenario) or create \u0026 setup it programatically.\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    android:id=\"@+id/ccll_corner_cut_provider\"\n    app:ccll_corner_cut_depth=\"@dimen/corner_cut_depth\"\n    app:ccll_corner_cut_length=\"@dimen/corner_cut_length\"\n    app:ccll_corner_cut_type=\"bevel\"/\u003e\n```\n2. Set a `CornerCutProvider`. \n```kotlin\nccll_corner_cut_provider.setCornerCutProvider { view, cutout, cutCorner, rectF -\u003e\n    when (cutCorner) {\n        CornerCutFlag.START_TOP -\u003e {\n            rectF.inset(inset, inset) // inset - globally defined property\n            cutout.moveTo(rectF.left, rectF.top)\n            cutout.lineTo(rectF.right, rectF.top)\n            cutout.lineTo(rectF.left, rectF.bottom)\n            true // accept left top corner\n        }\n        \n        CornerCutFlag.END_BOTTOM -\u003e {\n            // complex pacman path\n            ... \n            true // accept right bottom corner\n        }\n        \n        else -\u003e false // skip the rest of the corners and treat them by default settings\n    }\n}\n```\n\nHere, we simply override left top and right bottom corner cuts with the custom ones. They are accepted by returning `true` as a last statement, otherwise respective corner would be handled by its default settings (if any).\n\nWhen is necessary to compose `cutout` path with nested cutout pathes, use either `Path.addPath()` function (with different `fillType`) or `Path.op()` function with different `Path.Op` modes. \n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/corner_cut_provider_example_1.jpg\" width=\"300\" height=\"auto\"\u003e\n\n**Example 2**.\nIn some scenario you might need transform your cutout path (scale, rotate, skew, etc). For this purposes there is also optional function `getTransformationMatrix()` of `CornerCutProvider` interface.\\\nIn this example, there are 3 simple views with different background color below `CornerCutLinearLayout` with `CornerCutProvider`.\n\nAlso, as you can see from the image below, you could achieve animated effects by calling public function `invalidateCornerCutPath()` whenever it is necessary to update your view after changing your custom cutout relative values.\n\nAforementioned views become visible through cutout. Moreover shadow is also properly drawn around cutout. And this cutout exceeds its recommended by `rectF` bounds. For such purposes better use `CustomCutoutProvider`. \n\n```kotlin\nccll_corner_cut_example_2.setCornerCutProvider(\n            { view, _, _, _ -\u003e\n                val matrix = Matrix()\n                val pb = view.paddedBounds\n                matrix.postRotate(currentRotationAngle, pb.centerX(), pb.centerY())\n                matrix // returns matrix that will be applied to cutout path. Null by default\n            },\n            \n            { view, cutout, cutCorner, rectF -\u003e\n                when (cutCorner) {\n                    CornerCutLinearLayout.CornerCutFlag.START_TOP -\u003e {\n                        with(view.paddedBounds) {\n                            cutout.addRect(\n                                centerX() - rectF.width() / 2.0F,\n                                centerY() - rectF.height() / 2.0F,\n                                centerX() + rectF.width() / 2.0F,\n                                centerY() + rectF.height() / 2.0F,\n                                Path.Direction.CW\n                            )\n                        }\n                        true\n                    }\n\n                    else -\u003e false\n                }\n            }\n        )\n```\n\n\u003cimg src=\"/assets/images/corner_cut_provider_example_2.gif\" width=\"300\" height=\"auto\"\u003e\n\n### Child Corner Cut Provider\n`ChildCornerCutProvider` is almost the same as `CornerCutProvider`. Instead of `cutCorner` it has `cutEdge` and additionally possible contact children - `relativeCutTopChild` \u0026 `relativeCutBottomChild`.\n\n**Example 1**.\n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    android:id=\"@+id/ccll_child_cut_provider_example_1\"\n    app:ccll_child_side_cut_flag=\"start\"\n    app:ccll_corner_cut_flag=\"none\"\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\n```kotlin\nccll_child_cut_provider_example_1.setChildCornerCutProvider { view, cutout, _, rectF, _, _ -\u003e\n    with(cutout) {\n        moveTo(rectF.centerX(), rectF.top)\n        arcTo(...)\n        lineTo(rectF.centerX() + rectF.width(), rectF.bottom)\n        arcTo(...)\n        lineTo(rectF.centerX(), rectF.top)\n        val halfChordWidth = rectF.height() / 2.0F\n        addCircle(...)\n        moveTo(rectF.centerX() + rectF.width(), rectF.top)\n        lineTo(view.paddedBounds.right - rectF.width() / 2.0F, rectF.centerY())\n        lineTo(rectF.centerX() + rectF.width(), rectF.bottom)\n        lineTo(rectF.centerX() + rectF.width(), rectF.top)\n    }\n    true // accept custom cutout\n}\n```\n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/child_corner_cut_provider_example_1.jpg\" width=\"300\" height=\"auto\"\u003e\n\n\u003e Note that in this example only left side corner cuts are build with custom cutout provider. This is because providers is only called for `cutSide`'s \u0026 `cutCorner`'s specified by `ccll_child_side_cut_flag` \u0026 `ccll_corner_cut_flag`, respectively.\n\n**Example 2**.\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    android:id=\"@+id/ccll_child_cut_provider_example_2\"\n    app:ccll_child_corner_cut_type=\"rectangle_inverse\"\n    app:ccll_corner_cut_flag=\"none\"\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n```kotlin\nccll_showcase_custom_child_cut_provider_mixed.setChildCornerCutProvider(\n    { _, _, cutSide, rectF, _, _ -\u003e\n        val matrix = Matrix()\n        when (cutSide) {\n            CornerCutLinearLayout.ChildSideCutFlag.START -\u003e {\n                matrix.postSkew(-0.25F, 0.0F, rectF.centerX(), rectF.centerY())\n            }\n            CornerCutLinearLayout.ChildSideCutFlag.END -\u003e {\n                matrix.postRotate(-10.0F, rectF.centerX(), rectF.centerY())\n                matrix.postTranslate(-rectF.width() / 2.0F, 0.0F)\n            }\n        }\n        matrix // return transformation matrix that will be applied over previously defined cutouts\n    },\n    \n    { view, cutout, cutSide, rectF, relativeCutTopChild, _ -\u003e\n        when (cutSide) {\n            CornerCutLinearLayout.ChildSideCutFlag.START -\u003e {\n                if (view.indexOfChild(relativeCutTopChild ?: return@setChildCornerCutProvider false) != 1) return@setChildCornerCutProvider false\n                // cutout star path\n                true // accept path for only 2 (index 1) start side cutout\n            }\n            CornerCutLinearLayout.ChildSideCutFlag.END -\u003e {\n                if (view.indexOfChild(relativeCutTopChild ?: return@setChildCornerCutProvider false) != 0) return@setChildCornerCutProvider false\n                // cutout star path\n                true // accept path for only 1 (index 0) end side cutout\n            }\n            else -\u003e false\n        }\n    }\n)\n```\n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/child_corner_cut_provider_example_2.jpg\" width=\"300\" height=\"auto\"\u003e\n\n### Custom Cutout Provider\nThis type of provider (`CustomCutoutProvider`) is similar to previous cut providers. The only difference is that you could add many cutout providers and the `rectF` parameter in a both interface's functions return view's padded bounds.\n\n### Custom View Area Provider\n`CustomViewAreaProvider` might be useful in case you need to show custom area of view. Posibilities are only limited by your imagination and Android hardware. May require little knowledge of path composition, path op modes, fill types, etc.\n\n**Example 1**.\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    ...\n    android:id=\"@+id/ccll_custom_view_area_provider_example_1\"\n    app:ccll_child_side_cut_flag=\"none\"\n    app:ccll_corner_cut_flag=\"none\"\n    app:ccll_custom_shadow_color=\"@color/shadow_color\"\n    app:ccll_custom_shadow_radius=\"@dimen/shadow_radius\"\u003e\n\n    \u003cTextView\n        ...\n        android:layout_marginEnd=\"@dimen/offset_48\"\n        android:ellipsize=\"end\"\n        android:padding=\"@dimen/offset_16\"\n        android:text=\"Lorem ipsum dolor sit amet...\" /\u003e\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n```kotlin\nccll_custom_view_area_provider_example_1.setCustomViewAreaProvider { view, path, rectF -\u003e\n    // properties\n    val offset = view[0].marginEnd\n    val cornerRadius = rectF.height() / 4.0F\n    val tailCircleRadius = cornerRadius / 2.0F\n    val innerTailCircleRadius = tailCircleRadius / 2.0F\n    val smallCornerRadius = cornerRadius / 4.0F\n    \n    // left part: round rect\n    path.addRoundRect(...)\n    \n    // right part: tail\n    path.moveTo(rectF.right - offset, rectF.top + cornerRadius)\n    path.arcTo(...)\n    path.lineTo(rectF.right - tailCircleRadius, rectF.centerY() - innerTailCircleRadius)\n    path.lineTo(rectF.right - offset + innerTailCircleRadius, rectF.centerY() - innerTailCircleRadius)\n    path.arcTo(...)\n    path.lineTo(rectF.right - tailCircleRadius, rectF.centerY() + innerTailCircleRadius)\n    path.arcTo(...)\n    path.lineTo(rectF.right - offset, rectF.top + cornerRadius)\n    path.addCircle(rectF.right - tailCircleRadius, rectF.centerY(), tailCircleRadius,  Path.Direction.CW)\n    path.addCircle(rectF.right - tailCircleRadius, rectF.centerY(), innerTailCircleRadius, Path.Direction.CCW)\n}\n```\n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/view_area_provider_example_1.gif\" width=\"500\" height=\"auto\"\u003e\n\n**Example 2**.\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    android:id=\"@+id/ccll_custom_view_area_provider_example_2\"\n    android:gravity=\"center_horizontal\"\n    android:orientation=\"horizontal\"\n    android:padding=\"@dimen/offset_16\"\n    app:ccll_child_side_cut_flag=\"none\"\n    app:ccll_corner_cut_flag=\"none\"\n    app:ccll_could_draw_custom_shadow_over_user_defined_padding=\"true\"\n    app:ccll_custom_shadow_color=\"@color/accent_secondary\"\n    app:ccll_custom_shadow_radius=\"@dimen/elevation_16\"\n    app:ccll_is_custom_shadow_auto_padding_enabled=\"false\"\u003e\n\n    \u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n        ...\n        android:rotation=\"10\"\n        android:rotationX=\"35\"\n        android:translationX=\"24dp\"\n        app:ccll_child_side_cut_flag=\"none\"\n        app:ccll_corner_cut_type=\"oval_inverse\"\n        app:ccll_corner_cut_size=\"@dimen/corner_cut_size\"\u003e\n        ...\n    \u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n\n    \u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n        ...\n        app:ccll_corner_cut_size=\"@dimen/corner_cut_size_2\"\n        android:layout_marginStart=\"@dimen/offset_16\"\n        android:layout_marginEnd=\"@dimen/offset_48\"/\u003e\n\n    \u003cView\n        ...\n        android:background=\"#8010A7E8\" /\u003e\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\nIn this example `CornerCutLinearLayout` has nested `CornerCutLinearLayout` (first two children) and simple view (3rd child).\\\n**First child** is transformed (constantly running animation): rotated around x, y \u0026 z sequentially.\\\n**Second child** is continuously animated (translation Y) as well. It also has its own `CustomCutoutProvider` in a form of a star.\\\n**Third child** is a regular view with semi-transparent background.\n\nAlso parent `CustomCutoutProvider` has `CustomCutoutProvider` set programatically (curved lines path). In this examples we want to build shadow upon only children visible area also modifying some of them (virtual corner cuts for 3rd child).\n\n```kotlin\n// 1. Add Custom Cutout Provider\nval waveLineCutWidth = resources.getDimension(R.dimen.offset_12)\nval waveLineHeight = resources.getDimension(R.dimen.offset_48)\nval halfWaveLineHeight = waveLineHeight / 2.0F\nval halfWaveLineCutWidth = waveLineCutWidth / 2.0F\nccll_custom_view_area_provider_example_2.addCustomCutoutProvider { _, cutout, rectF -\u003e\n    cutout.moveTo(rectF.left, rectF.centerY() - halfWaveLineCutWidth)\n    cutout.lineTo(rectF.left + rectF.width() / 4.0F, rectF.centerY() - halfWaveLineCutWidth - halfWaveLineHeight)\n    cutout.lineTo(rectF.right - rectF.width() / 4.0F, rectF.centerY() - halfWaveLineCutWidth + halfWaveLineHeight)\n    cutout.lineTo(rectF.right, rectF.centerY() - halfWaveLineCutWidth)\n    cutout.lineTo(rectF.right, rectF.centerY() + halfWaveLineCutWidth)\n    cutout.lineTo(rectF.right - rectF.width() / 4.0F, rectF.centerY() + halfWaveLineCutWidth + halfWaveLineHeight)\n    cutout.lineTo(rectF.left + rectF.width() / 4.0F, rectF.centerY() + halfWaveLineCutWidth - halfWaveLineHeight)\n    cutout.lineTo(rectF.left, rectF.centerY() + halfWaveLineCutWidth)\n    cutout.lineTo(rectF.left, rectF.centerY() - halfWaveLineCutWidth)\n}\n\n// 2. Set Custom View Area Provider\nccll_showcase_custom_view_area_provider_example_2.setCustomViewAreaProvider { view, path, _ -\u003e\n    view.forEach {\n        tempPath.rewind()\n        if (it is CornerCutLinearLayout) {\n            tempPath.offset(-it.left.toFloat(), -it.top.toFloat())\n            tempPath.addPath(it.viewAreaPath) // nested ccll visible area path\n            tempPath.transform(it.matrix)\n            tempPath.offset(it.left.toFloat(), it.top.toFloat())\n        } else {\n            tempRectF.set(it.left.toFloat(), it.top.toFloat(), it.right.toFloat(), it.bottom.toFloat())\n            val childCornerRadius = min(tempRectF.width(), tempRectF.height()) / 6.0F\n            tempPath.addRoundRect(tempRectF, childCornerRadius, childCornerRadius, Path.Direction.CW)\n            tempPath.offset(-it.left.toFloat(), -it.top.toFloat())\n            tempPath.transform(it.matrix)\n            tempPath.offset(it.left.toFloat(), it.top.toFloat())\n        }\n        path.op(tempPath, Path.Op.UNION)\n    }\n}\n```\n\nNote that 3rd child is clipped virtually. So when its bound overlay another visible area bounds corners of 3rd child become visible. \n\nAs you see custom shadow are build correctly upon custom visible view area (including children cutouts and transformations) \u0026 global custom cutouts.\n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/view_area_provider_example_2.gif\" width=\"500\" height=\"auto\"\u003e\n\nWhen you nest `CornerCutLinearLayout` in another `CornerCutLinearLayout` and work with `CustomViewAreaProvider` it might be necessary to get current visible view area path. The copy of it could be obtained via `CornerCutLinearLayout.viewAreaPath`\\*. In similar manner widget's padded bounds could be obtained (`CornerCutLinearLayout.paddedBounds`).\n\n\u003e\\* - custom shadow are build upon `viewAreaPath`.\n\n### Custom Divider Provider\nSometimes you might want to have some not trivial different dividers at different positions mixed with default dividers. In a such scenario, `CustomDividerProvider` might come handy.\n\n**Example 1**.\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    android:id=\"@+id/ccll_custom_divider_provider_example_1\"\n    app:ccll_child_side_cut_flag=\"none\"\n    app:ccll_corner_cut_flag=\"all\"\n    app:ccll_corner_cut_type=\"oval\"\n    app:ccll_custom_divider_show_flag=\"container_beginning|middle|container_end\"\n    app:ccll_should_use_max_allowed_corner_cut_depth_or_length_to_be_equal=\"true\"\n    app:ccll_should_use_max_allowed_corner_cut_size=\"true\"\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n\nThen we define globally divider paint:\n\n```kotlin\nccll_custom_divider_provider_example_1.doOnNonNullSizeLayout {\n    val pb = it.paddedBounds\n    it.customDividerProviderPaint.shader = RadialGradient(\n        pb.centerX(), pb.centerY(),\n        hypot(pb.width() / 2.0F, pb.height() / 2.0F) * 0.8F,\n        Color.BLACK, Color.WHITE,\n        Shader.TileMode.CLAMP\n    )\n}\n```\n\nLastly, we add `CustomDividerProvider`:\n\n```kotlin\nccll_custom_divider_provider_example_1.setCustomDividerProvider { _, dividerPath, dividerPaint, showDividerFlag, dividerTypeIndex, rectF -\u003e\n    when (showDividerFlag) {\n        CornerCutLinearLayout.CustomDividerShowFlag.CONTAINER_BEGINNING -\u003e {\n            dividerPaint.style = Paint.Style.STROKE\n            dividerPaint.strokeWidth = triangleHeight\n            dividerPaint.pathEffect = PathDashPathEffect(topDividerTrianglePath, triangleBaseWidth, 0.0F, PathDashPathEffect.Style.TRANSLATE)\n            dividerPath.moveTo(rectF.left, rectF.top)\n            dividerPath.lineTo(rectF.right, rectF.top)\n        }\n\n        CornerCutLinearLayout.CustomDividerShowFlag.MIDDLE -\u003e {\n            dividerPaint.style = Paint.Style.STROKE\n            if (dividerTypeIndex == 0) {\n                dividerPaint.strokeWidth = circleRadius\n                dividerPaint.pathEffect = PathDashPathEffect(circleDotDividerPath, triangleBaseWidth, 0.0F, PathDashPathEffect.Style.TRANSLATE)\n                dividerPath.moveTo(rectF.left, rectF.centerY())\n                dividerPath.lineTo(rectF.right + triangleBaseWidth, rectF.centerY())\n            } else {\n                dividerPaint.strokeWidth = circleRadius\n                dividerPaint.pathEffect = PathDashPathEffect(diamondDotDividerPath, triangleBaseWidth, 0.0F, PathDashPathEffect.Style.TRANSLATE)\n                dividerPath.moveTo(rectF.left, rectF.centerY())\n                dividerPath.lineTo(rectF.right + triangleBaseWidth, rectF.centerY())\n            }\n        }\n\n        CornerCutLinearLayout.CustomDividerShowFlag.CONTAINER_END -\u003e {\n            dividerPaint.style = Paint.Style.STROKE\n            dividerPaint.strokeWidth = triangleHeight\n            dividerPaint.pathEffect = PathDashPathEffect(bottomDividerTrianglePath, triangleBaseWidth, 0.0F, PathDashPathEffect.Style.TRANSLATE)\n            dividerPath.moveTo(rectF.left, rectF.top)\n            dividerPath.lineTo(rectF.right, rectF.top)\n        }\n    }\n    true // accept divider path\n}\n```\n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/divider_provider_example_1.jpg\" width=\"200\" height=\"auto\"\u003e\n\n**Example 2**.\nThis example shows the combination of custom and default's dividers. \n\n```xml\n\u003cio.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\n    android:id=\"@+id/ccll_custom_divider_provider_example_2\"\n    app:ccll_child_corner_cut_type=\"oval_inverse\"\n    app:ccll_corner_cut_flag=\"all\"\n    app:ccll_custom_divider_color=\"@color/divider\"\n    app:ccll_custom_divider_dash_gap=\"@dimen/divider_dash_gap\"\n    app:ccll_custom_divider_dash_width=\"@dimen/divider_dash_width\"\n    app:ccll_custom_divider_height=\"@dimen/divider_height\"\n    app:ccll_custom_divider_line_cap=\"round\"\n    app:ccll_custom_divider_show_flag=\"middle\"\n    app:ccll_custom_shadow_color=\"@color/accent_secondary\"\u003e\n    ...\n\u003c/io.devlight.xtreeivi.cornercutlinearlayout.CornerCutLinearLayout\u003e\n```\n```kotlin\nccll_custom_divider_provider_example_2.setCustomDividerProvider { _, dividerPath, dividerPaint, showDividerFlag, dividerTypeIndex, rectF -\u003e\n    when (showDividerFlag) {\n        CornerCutLinearLayout.CustomDividerShowFlag.MIDDLE -\u003e {\n            dividerPaint.style = Paint.Style.STROKE\n            when (dividerTypeIndex) {\n                0 -\u003e {\n                    dividerPaint.shader = RadialGradient(\n                        rectF.centerX(), rectF.centerY(),\n                        rectF.width() / 2.0F, Color.GREEN, Color.RED,\n                        Shader.TileMode.MIRROR\n                    )\n                    dividerPaint.strokeWidth = circleRadius\n                    dividerPaint.pathEffect = PathDashPathEffect(diamondDotDividerPath, triangleBaseWidth, 0.0F, PathDashPathEffect.Style.TRANSLATE)\n                    dividerPath.moveTo(rectF.left, rectF.centerY())\n                    dividerPath.lineTo(rectF.right + triangleBaseWidth, rectF.centerY())\n                    return@setCustomDividerProvider true // accept divider and draw it\n                }\n                \n                2 -\u003e {\n                    dividerPaint.shader = LinearGradient(\n                        rectF.centerX(), rectF.centerY() - halfWaveHeight,\n                        rectF.centerX(), rectF.centerY() + halfWaveHeight,\n                        Color.BLUE, Color.YELLOW, Shader.TileMode.CLAMP\n                    )\n                    dividerPaint.strokeWidth = halfWaveHeight * 2.0F\n                    dividerPaint.pathEffect = PathDashPathEffect( wavePath, halfWaveWidth * 2.0F, 0.0F, PathDashPathEffect.Style.TRANSLATE)\n                    dividerPath.moveTo(rectF.left, rectF.centerY())\n                    dividerPath.lineTo(rectF.right, rectF.centerY())\n                    return@setCustomDividerProvider true // accept divider and draw it\n                }\n                \n                else -\u003e return@setCustomDividerProvider false // skip divider and draw default\n            }\n        }\n    }\n    false // skip divider and draw default\n}\n```\n\nThe result would be as follow:\n\n\u003cimg src=\"/assets/images/divider_provider_example_2.jpg\" width=\"200\" height=\"auto\"\u003e\n\n## Sample App\nIn order to take closer look over examples provided and library in general, please run the sample app.\n\n## Author\nCreated by [Mykola Melnyk](https://github.com/XtreeIvI) - [@xtreeivi](mailto:xtreeivi@gmail.com)\n\n### Donation\nI would appreciate if you \"toss the coin to your faithful servant\".\\\nDetails: **5432 5912 5316 4615** (MasterCard)\n\n## Company\n[![Facebook](https://drive.google.com/uc?export=download\u0026id=0BxPO_UeS7wScaGhGVFNKU0VxMnc)](https://www.facebook.com/devlightagency)\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[![Twitter](https://drive.google.com/uc?export=download\u0026id=0BxPO_UeS7wScZ1ExQWh5cHF5cVE)](https://twitter.com/DevLightIO)\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[![LinkedIn](https://drive.google.com/uc?export=download\u0026id=0BxPO_UeS7wSccGZINzEycE1nVFE)](https://www.linkedin.com/company/devlight)\n\n## Created by [Mykola Melnyk](https://github.com/XtreeIvI) - [@xtreeivi](mailto:xtreeivi@gmail.com)\n[Here](https://github.com/DevLight) you can see open source works developed by Devlight LLC.  \nThis and another works is an exclusive property of Devlight LLC. \n\nIf you want to use this library in applications which will be available on Google Play, please report us or author of the library about it.\n\nWhether you're searching for a new partner or trusted team for creating your new great product we are always ready to start work with you. \n\nYou can contact us: info@devlight.io or opensource@devlight.io.  \nThanks in advance.\n\nDevlight LLC, 2020 \n[devlight.io](http://devlight.io)\n\n## License\nPlease see [LICENSE](/LICENSE.txt)","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDevlight%2FCornerCutLinearLayout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDevlight%2FCornerCutLinearLayout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDevlight%2FCornerCutLinearLayout/lists"}