[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7571":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":28,"readmeContent":29,"aiSummary":30,"trendingCount":16,"starSnapshotCount":16,"syncStatus":31,"lastSyncTime":32,"discoverSource":33},7571,"paris","airbnb\u002Fparis","airbnb","Define and apply styles to Android views programmatically","",null,"Kotlin",1908,85,24,51,0,18.8,"Apache License 2.0",false,"master",true,[23,24,25,26,27],"android","android-ui","design-systems","kotlin","styles","2026-06-12 02:01:41","# Paris\nParis lets you define and apply styles programmatically to Android views, including custom attributes.\n\n* Apply styles programmatically at any time.\n* Combine multiple styles together.\n* Create styles programmatically (as opposed to using XML).\n* Use annotations to easily support custom attributes (inspired by [Barber](https:\u002F\u002Fgithub.com\u002Fhzsweers\u002Fbarber)).\n* Declare explicitly supported styles for your custom views.\n* And much more...\n\n## Installation\n\nIn your project's `build.gradle`:\n```gradle\ndependencies {\n    implementation 'com.airbnb.android:paris:2.2.1'\n    \u002F\u002F Apply the Paris processor if you're using Paris annotations for code gen.\n    kapt 'com.airbnb.android:paris-processor:2.2.1'\n    \u002F\u002F or if you are using Kotlin Symbol Processing\n    ksp 'com.airbnb.android:paris-processor:2.2.1'\n}\n```\n\nTo use Paris in a library module see [Library Modules](..\u002F..\u002Fwiki\u002FLibrary-Modules).\n\n## Quick Start\n\n### Applying an XML-Defined Style\n\n```kotlin\nmyView.style(R.style.MyStyle)\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\nParis.style(myView).apply(R.style.MyStyle);\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nWhere `myView` is an arbitrary view instance, `MyStyle` an XML-defined style, and `style` an extension function provided by Paris. Many but not all attributes are supported, for more see [Supported View Types and Attributes](..\u002F..\u002Fwiki\u002FSupported-View-Types-and-Attributes).\n\n### Combining 2 or More Styles\n\n```kotlin\nmyView.style {\n    add(R.style.StyleA)\n    add(R.style.StyleB)\n    …\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\nParis.styleBuilder(myView)\n        .add(R.style.StyleA)\n        .add(R.style.StyleB)\n        …\n        .apply();\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nIn cases where there's some overlap the attribute value from the last style added prevails. For more see [Combining Styles](..\u002F..\u002Fwiki\u002FBuilding-and-Applying-Styles#combining-styles).\n\n### Defining Styles Programmatically\n\n```kotlin\ntextView.style {\n    \u002F\u002F Using an actual value.\n    textColor(Color.GREEN)\n    \u002F\u002F Or a resource.\n    textSizeRes(R.dimen.my_text_size_small)\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\nParis.styleBuilder(textView)\n        \u002F\u002F Using an actual value.\n        .textColor(Color.GREEN)\n        \u002F\u002F Or a resource.\n        .textSizeRes(R.dimen.my_text_size_small)\n        .apply();\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nCan be combined with style resources as well:\n```kotlin\ntextView.style {\n    \u002F\u002F Adds all the attributes defined in the MyGreenTextView style.\n    add(R.style.MyGreenTextView)\n    textSizeRes(R.dimen.my_text_size_small)\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\nParis.styleBuilder(textView)\n        \u002F\u002F Adds all the attributes defined in the MyGreenTextView style.\n        .add(R.style.MyGreenTextView)\n        .textSizeRes(R.dimen.my_text_size_small)\n        .apply();\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nFor more see [Defining Styles Programmatically](..\u002F..\u002Fwiki\u002FBuilding-and-Applying-Styles#defining-styles-programmatically).\n\n### Custom View Attributes\n\nAttributes are declared as followed:\n```xml\n\u003Cdeclare-styleable name=\"MyView\">\n    \u003Cattr name=\"title\" format=\"string\" \u002F>\n    \u003Cattr name=\"image\" format=\"reference\" \u002F>\n    \u003Cattr name=\"imageSize\" format=\"dimension\" \u002F>\n\u003C\u002Fdeclare-styleable>\n```\n\nThe custom view is annotated with `@Styleable` and `@Attr`:\n```kotlin\n\u002F\u002F The value here corresponds to the name chosen in declare-styleable.\n@Styleable(\"MyView\")\nclass MyView(…) : ViewGroup(…) {\n\n    init {\n        \u002F\u002F This call enables the custom attributes when used in XML layouts. It\n        \u002F\u002F extracts styling information from AttributeSet like it would a StyleRes.\n        style(attrs)\n    }\n\n    @Attr(R.styleable.MyView_title)\n    fun setTitle(title: String) {\n        \u002F\u002F Automatically called with the title value (if any) when an AttributeSet\n        \u002F\u002F or StyleRes is applied to the MyView instance.\n    }\n\n    @Attr(R.styleable.MyView_image)\n    fun setImage(image: Drawable?) {\n        \u002F\u002F Automatically called with the image value (if any) when an AttributeSet\n        \u002F\u002F or StyleRes is applied to the MyView instance.\n    }\n\n    @Attr(R.styleable.MyView_imageSize)\n    fun setImageSize(@Px imageSize: Int) {\n        \u002F\u002F Automatically called with the imageSize value (if any) when an\n        \u002F\u002F AttributeSet or StyleRes is applied to the MyView instance.\n    }\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\n\u002F\u002F The value here corresponds to the name chosen in declare-styleable.\n@Styleable(\"MyView\")\npublic class MyView extends ViewGroup {\n\n    public MyView(Context context) {\n        super(context);\n    }\n\n    public MyView(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public MyView(Context context, AttributeSet attrs, int defStyle) {\n        this(context, attrs, defStyle);\n        \u002F\u002F This call enables the custom attributes when used in XML layouts. It\n        \u002F\u002F extracts styling information from AttributeSet like it would a StyleRes.\n        Paris.style(this).apply(attrs);\n    }\n\n    @Attr(R.styleable.MyView_title)\n    public void setTitle(String title) {\n        \u002F\u002F Automatically called with the title value (if any) when an AttributeSet\n        \u002F\u002F or StyleRes is applied to the MyView instance.\n    }\n\n    @Attr(R.styleable.MyView_image)\n    public void setImage(Drawable image) {\n        \u002F\u002F Automatically called with the image value (if any) when an AttributeSet\n        \u002F\u002F or StyleRes is applied to the MyView instance.\n    }\n\n    @Attr(R.styleable.MyView_imageSize)\n    public void setImageSize(@Px int imageSize) {\n        \u002F\u002F Automatically called with the imageSize value (if any) when an\n        \u002F\u002F AttributeSet or StyleRes is applied to the MyView instance.\n    }\n}\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nThe `@Attr`-annotated methods will be called by Paris when the view is inflated with an `AttributeSet` or when a style is applied.\n\nFor more see [Custom View Attributes](..\u002F..\u002Fwiki\u002FCustom-View-Attributes).\n\n### Styling Subviews\n\nAttributes are declared as followed for the 2 subviews we'd like to be able to style:\n```xml\n\u003Cdeclare-styleable name=\"MyHeader\">\n    \u003Cattr name=\"titleStyle\" format=\"reference\" \u002F>\n    \u003Cattr name=\"subtitleStyle\" format=\"reference\" \u002F>\n    ...\n\u003C\u002Fdeclare-styleable>\n```\n\nThe subview fields are annotated with `@StyleableChild`:\n```kotlin\n@Styleable(\"MyHeader\")\nclass MyHeader(…) : ViewGroup(…) {\n\n    @StyleableChild(R.styleable.MyHeader_titleStyle)\n    internal val title: TextView …\n    \n    @StyleableChild(R.styleable.MyHeader_subtitleStyle)\n    internal val subtitle: TextView …\n    \n    init {\n        style(attrs)\n    }\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\n@Styleable(\"MyHeader\")\npublic class MyHeader extends ViewGroup {\n\n    @StyleableChild(R.styleable.MyHeader_titleStyle)\n    TextView title;\n    \n    @StyleableChild(R.styleable.MyHeader_subtitleStyle)\n    TextView subtitle;\n    \n    …\n    \u002F\u002F Make sure to call Paris.style(this).apply(attrs) during initialization.\n}\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nThe title and subtitle styles can now be part of `MyHeader` styles:\n```xml\n\u003CMyHeader\n    ...\n    app:titleStyle=\"@style\u002FTitle2\"\n    app:subtitleStyle=\"@style\u002FRegular\" \u002F>\n```\n\n```kotlin\nmyHeader.style {\n    \u002F\u002F Defined in XML.\n    titleStyle(R.style.Title2)\n    \u002F\u002F Defined programmatically.\n    subtitleStyle {\n        textColorRes(R.color.text_color_regular)\n        textSizeRes(R.dimen.text_size_regular)\n    }\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\nParis.styleBuilder(myHeader)\n        \u002F\u002F Defined in XML.\n        .titleStyle(R.style.Title2)\n        \u002F\u002F Defined programmatically.\n        .subtitleStyle((builder) -> builder\n                .textColorRes(R.color.text_color_regular)\n                .textSizeRes(R.dimen.text_size_regular))\n        .apply();\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\n**Attention:** Extension functions like `titleStyle` and `subtitleStyle` are generated during compilation by the Paris annotation processor. When new `@StyleableChild` annotations are added, the project must be (re)compiled once for the related functions to become available.\n\nFor more see [Styling Subviews](..\u002F..\u002Fwiki\u002FCustom-Views#styling-subviews).\n\n### Linking Styles to Views\n\n```kotlin\n@Styleable\nclass MyView(…) : View(…) {\n\n    companion object {\n        \u002F\u002F For styles defined in XML.\n        @Style\n        val RED_STYLE = R.style.MyView_Red\n\n        \u002F\u002F For styles defined programmatically.\n        @Style\n        val GREEN_STYLE = myViewStyle {\n            background(R.color.green)\n        }\n    }\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\n@Styleable\npublic class MyView extends View {\n\n    \u002F\u002F For styles defined in XML.\n    @Style\n    static final int RED_STYLE = R.style.MyView_Red;\n\n    \u002F\u002F For styles defined programmatically.\n    @Style\n    static void greenStyle(MyViewStyleApplier.StyleBuilder builder) {\n        builder.background(R.color.green);\n    }\n}\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\nHelper methods are generated for each linked style:\n```kotlin\nmyView.style { addRed() } \u002F\u002F Equivalent to style(R.style.MyView_Red)\nmyView.style { addGreen() } \u002F\u002F Equivalent to add(MyView.GREEN_STYLE)\n\nmyView.style {\n    addRed() \u002F\u002F Equivalent to add(R.style.MyView_Red)\n    addGreen() \u002F\u002F Equivalent to add(MyView.GREEN_STYLE)\n    …\n}\n```\n\u003Cdetails>\u003Csummary>Click to see the example in Java.\u003C\u002Fsummary>\n\n```java\nParis.style(myView).applyRed(); \u002F\u002F Equivalent to apply(R.style.MyView_Red)\nParis.style(myView).applyGreen(); \u002F\u002F No equivalent.\n\nParis.styleBuilder(myView)\n        .addRed() \u002F\u002F Equivalent to add(R.style.MyView_Red)\n        .addGreen() \u002F\u002F No equivalent.\n        …\n        .apply();\n```\n\u003C\u002Fdetails>\u003Cbr\u002F>\n\n**Attention:** Extension functions like `addRed` and `addGreen` are generated during compilation by the Paris annotation processor. When new `@Style` annotations are added, the project must be (re)compiled once for the related functions to become available.\n\nFor more see [Linking Styles to Custom Views](..\u002F..\u002Fwiki\u002FCustom-Views#linking-styles-to-custom-views).\n\n## Documentation\n\nSee examples and browse complete documentation at the [Paris Wiki](..\u002F..\u002Fwiki).\n\nIf you still have questions, feel free to create a new issue.\n\n## Contributing\n\nWe love contributions! Check out our [contributing guidelines](CONTRIBUTING.md) and be sure to follow our [code of conduct](CODE_OF_CONDUCT.md).\n\n## License\n\n```\nCopyright 2018 Airbnb, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","Paris 是一个用于在 Android 视图中以编程方式定义和应用样式的库。它支持在任何时候以编程方式应用样式，允许组合多个样式，并且可以创建不依赖于 XML 的样式。通过注解轻松支持自定义属性，同时声明性地支持自定义视图的样式。该库使用 Kotlin 编写，适合需要动态改变 UI 样式或希望减少 XML 依赖的 Android 开发场景。其灵活性使得开发者能够在运行时根据条件调整界面风格，从而提高开发效率与用户体验的一致性。",2,"2026-06-11 03:13:06","top_language"]