Paris позволяет программно определять и применять стили к представлениям Android, включая пользовательские атрибуты.
В build.gradle
вашего проекта:
dependencies {
implementation ' com.airbnb.android:paris:2.0.0 '
// Apply the Paris processor if you're using Paris annotations for code gen.
kapt ' com.airbnb.android:paris-processor:2.0.0 '
// or if you are using Kotlin Symbol Processing
ksp ' com.airbnb.android:paris-processor:2.0.0 '
}
Чтобы использовать Париж в библиотечном модуле, см. «Библиотечные модули».
myView.style( R .style. MyStyle )
Paris . style ( myView ). apply ( R . style . MyStyle );
Где myView
— это произвольный экземпляр представления, MyStyle
стиль, определенный в XML, а style
— функция расширения, предоставленная Paris. Поддерживаются многие, но не все атрибуты. Дополнительные сведения см. в разделе Поддерживаемые типы представлений и атрибуты.
myView.style {
add( R .style. StyleA )
add( R .style. StyleB )
…
}
Paris . styleBuilder ( myView )
. add ( R . style . StyleA )
. add ( R . style . StyleB )
…
. apply ();
В случаях некоторого перекрытия преобладает значение атрибута из последнего добавленного стиля. Дополнительную информацию см. в разделе «Комбинирование стилей».
textView.style {
// Using an actual value.
textColor( Color . GREEN )
// Or a resource.
textSizeRes( R .dimen.my_text_size_small)
}
Paris . styleBuilder ( textView )
// Using an actual value.
. textColor ( Color . GREEN )
// Or a resource.
. textSizeRes ( R . dimen . my_text_size_small )
. apply ();
Также можно комбинировать с ресурсами стиля:
textView.style {
// Adds all the attributes defined in the MyGreenTextView style.
add( R .style. MyGreenTextView )
textSizeRes( R .dimen.my_text_size_small)
}
Paris . styleBuilder ( textView )
// Adds all the attributes defined in the MyGreenTextView style.
. add ( R . style . MyGreenTextView )
. textSizeRes ( R . dimen . my_text_size_small )
. apply ();
Дополнительные сведения см. в разделе Программное определение стилей.
Атрибуты объявляются следующим образом:
< declare-styleable name = " MyView " >
< attr name = " title " format = " string " />
< attr name = " image " format = " reference " />
< attr name = " imageSize " format = " dimension " />
</ declare-styleable >
Пользовательское представление аннотируется @Styleable
и @Attr
:
// The value here corresponds to the name chosen in declare-styleable.
@Styleable( " MyView " )
class MyView (…) : ViewGroup(…) {
init {
// This call enables the custom attributes when used in XML layouts. It
// extracts styling information from AttributeSet like it would a StyleRes.
style(attrs)
}
@Attr( R .styleable. MyView_title )
fun setTitle ( title : String ) {
// Automatically called with the title value (if any) when an AttributeSet
// or StyleRes is applied to the MyView instance.
}
@Attr( R .styleable. MyView_image )
fun setImage ( image : Drawable ? ) {
// Automatically called with the image value (if any) when an AttributeSet
// or StyleRes is applied to the MyView instance.
}
@Attr( R .styleable. MyView_imageSize )
fun setImageSize (@Px imageSize : Int ) {
// Automatically called with the imageSize value (if any) when an
// AttributeSet or StyleRes is applied to the MyView instance.
}
}
// The value here corresponds to the name chosen in declare-styleable.
@ Styleable ( "MyView" )
public class MyView extends ViewGroup {
public MyView ( Context context ) {
super ( context );
}
public MyView ( Context context , AttributeSet attrs ) {
this ( context , attrs , 0 );
}
public MyView ( Context context , AttributeSet attrs , int defStyle ) {
this ( context , attrs , defStyle );
// This call enables the custom attributes when used in XML layouts. It
// extracts styling information from AttributeSet like it would a StyleRes.
Paris . style ( this ). apply ( attrs );
}
@ Attr ( R . styleable . MyView_title )
public void setTitle ( String title ) {
// Automatically called with the title value (if any) when an AttributeSet
// or StyleRes is applied to the MyView instance.
}
@ Attr ( R . styleable . MyView_image )
public void setImage ( Drawable image ) {
// Automatically called with the image value (if any) when an AttributeSet
// or StyleRes is applied to the MyView instance.
}
@ Attr ( R . styleable . MyView_imageSize )
public void setImageSize ( @ Px int imageSize ) {
// Automatically called with the imageSize value (if any) when an
// AttributeSet or StyleRes is applied to the MyView instance.
}
}
Методы с аннотацией @Attr
будут вызываться Paris, когда представление заполняется с помощью AttributeSet
или когда применяется стиль.
Дополнительные сведения см. в разделе Пользовательские атрибуты представления.
Атрибуты объявляются следующим образом для двух подпредставлений, которые мы хотели бы стилизовать:
< declare-styleable name = " MyHeader " >
< attr name = " titleStyle " format = " reference " />
< attr name = " subtitleStyle " format = " reference " />
...
</ declare-styleable >
Поля подпредставления помечены @StyleableChild
:
@Styleable( " MyHeader " )
class MyHeader (…) : ViewGroup(…) {
@StyleableChild( R .styleable. MyHeader_titleStyle )
internal val title : TextView …
@StyleableChild( R .styleable. MyHeader_subtitleStyle )
internal val subtitle : TextView …
init {
style(attrs)
}
}
@ Styleable ( "MyHeader" )
public class MyHeader extends ViewGroup {
@ StyleableChild ( R . styleable . MyHeader_titleStyle )
TextView title ;
@ StyleableChild ( R . styleable . MyHeader_subtitleStyle )
TextView subtitle ;
…
// Make sure to call Paris.style(this).apply(attrs) during initialization.
}
Стили заголовка и подзаголовка теперь могут быть частью стилей MyHeader
:
< MyHeader
...
app : titleStyle = " @style/Title2 "
app : subtitleStyle = " @style/Regular " />
myHeader.style {
// Defined in XML.
titleStyle( R .style. Title2 )
// Defined programmatically.
subtitleStyle {
textColorRes( R .color.text_color_regular)
textSizeRes( R .dimen.text_size_regular)
}
}
Paris . styleBuilder ( myHeader )
// Defined in XML.
. titleStyle ( R . style . Title2 )
// Defined programmatically.
. subtitleStyle (( builder ) -> builder
. textColorRes ( R . color . text_color_regular )
. textSizeRes ( R . dimen . text_size_regular ))
. apply ();
Внимание: функции расширения, такие как titleStyle
и subtitleStyle
генерируются во время компиляции обработчиком аннотаций Paris. При добавлении новых аннотаций @StyleableChild
проект необходимо (пере) скомпилировать один раз, чтобы соответствующие функции стали доступны.
Дополнительные сведения см. в разделе «Стилизация подпредставлений».
@Styleable
class MyView (…) : View(…) {
companion object {
// For styles defined in XML.
@Style
val RED_STYLE = R .style. MyView_Red
// For styles defined programmatically.
@Style
val GREEN_STYLE = myViewStyle {
background( R .color.green)
}
}
}
@ Styleable
public class MyView extends View {
// For styles defined in XML.
@ Style
static final int RED_STYLE = R . style . MyView_Red ;
// For styles defined programmatically.
@ Style
static void greenStyle ( MyViewStyleApplier . StyleBuilder builder ) {
builder . background ( R . color . green );
}
}
Вспомогательные методы генерируются для каждого связанного стиля:
myView.style { addRed() } // Equivalent to style(R.style.MyView_Red)
myView.style { addGreen() } // Equivalent to add(MyView.GREEN_STYLE)
myView.style {
addRed() // Equivalent to add(R.style.MyView_Red)
addGreen() // Equivalent to add(MyView.GREEN_STYLE)
…
}
Paris . style ( myView ). applyRed (); // Equivalent to apply(R.style.MyView_Red)
Paris . style ( myView ). applyGreen (); // No equivalent.
Paris . styleBuilder ( myView )
. addRed () // Equivalent to add(R.style.MyView_Red)
. addGreen () // No equivalent.
…
. apply ();
Внимание: функции расширения, такие как addRed
и addGreen
генерируются во время компиляции обработчиком аннотаций Paris. При добавлении новых аннотаций @Style
проект необходимо (пере) скомпилировать один раз, чтобы соответствующие функции стали доступны.
Дополнительные сведения см. в разделе «Связывание стилей с пользовательскими представлениями».
Посмотрите примеры и просмотрите полную документацию на Paris Wiki.
Если у вас остались вопросы, смело создавайте новую тему.
Мы любим вклад! Ознакомьтесь с нашими рекомендациями по участию и обязательно соблюдайте наш кодекс поведения.
Copyright 2018 Airbnb, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.