Skip to content

Commit d4f91b3

Browse files
committedApr 1, 2019
First Buttons implementation
We will have two implementation. Flexible Button and Material specific Button with text. Button with image is out of scope for now as it requires Image component to be implemented. Disabled button has wrong bg and text color for now. Styling for this to be added later. Bug: 113845528 Test: Button demo activity. Tests to be added later. Change-Id: Id55f6871a33515a20d7f5941e5e722d73f38f588
1 parent 135a11d commit d4f91b3

File tree

22 files changed

+756
-144
lines changed

22 files changed

+756
-144
lines changed
 

‎samples/UiMaterialDemos/src/main/AndroidManifest.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,14 @@
4545
<category android:name="androidx.ui.material.demos.SAMPLE_CODE" />
4646
</intent-filter>
4747
</activity>
48+
49+
<activity android:name="androidx.ui.material.demos.ButtonActivity"
50+
android:configChanges="orientation|screenSize"
51+
android:label="Button">
52+
<intent-filter>
53+
<action android:name="android.intent.action.MAIN" />
54+
<category android:name="androidx.ui.material.demos.SAMPLE_CODE" />
55+
</intent-filter>
56+
</activity>
4857
</application>
4958
</manifest>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2019 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/*
18+
* Copyright 2019 The Android Open Source Project
19+
*
20+
* Licensed under the Apache License, Version 2.0 (the "License");
21+
* you may not use this file except in compliance with the License.
22+
* You may obtain a copy of the License at
23+
*
24+
* http://www.apache.org/licenses/LICENSE-2.0
25+
*
26+
* Unless required by applicable law or agreed to in writing, software
27+
* distributed under the License is distributed on an "AS IS" BASIS,
28+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29+
* See the License for the specific language governing permissions and
30+
* limitations under the License.
31+
*/
32+
33+
package androidx.ui.material.demos
34+
35+
import android.app.Activity
36+
import android.os.Bundle
37+
import com.google.r4a.composer
38+
import com.google.r4a.setContent
39+
40+
class ButtonActivity : Activity() {
41+
42+
override fun onCreate(savedInstanceState: Bundle?) {
43+
super.onCreate(savedInstanceState)
44+
setContent { <ButtonDemo/>}
45+
}
46+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright 2019 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package androidx.ui.material.demos
18+
19+
import android.util.Log
20+
import androidx.ui.core.CraneWrapper
21+
import androidx.ui.core.Text
22+
import androidx.ui.core.dp
23+
import androidx.ui.core.withDensity
24+
import androidx.ui.layout.Center
25+
import androidx.ui.layout.Column
26+
import androidx.ui.layout.EdgeInsets
27+
import androidx.ui.layout.MainAxisAlignment
28+
import androidx.ui.layout.Padding
29+
import androidx.ui.material.Button
30+
import androidx.ui.material.Colors
31+
import androidx.ui.material.MaterialTheme
32+
import androidx.ui.material.borders.BorderRadius
33+
import androidx.ui.material.borders.BorderSide
34+
import androidx.ui.material.borders.RoundedRectangleBorder
35+
import androidx.ui.painting.Color
36+
import androidx.ui.painting.TextSpan
37+
import com.google.r4a.Composable
38+
import com.google.r4a.ambient
39+
import com.google.r4a.composer
40+
import com.google.r4a.unaryPlus
41+
42+
@Composable
43+
fun ButtonDemo() {
44+
val onClick: () -> Unit = { Log.e("ButtonDemo", "onClick") }
45+
<CraneWrapper>
46+
<MaterialTheme>
47+
<Center>
48+
<Column mainAxisAlignment=MainAxisAlignment.SpaceEvenly>
49+
<Button onClick text="LONG TEXT" />
50+
51+
<Button onClick text="SH" />
52+
53+
<Button
54+
onClick
55+
color=Color.Transparent
56+
text="NO BACKGROUND" />
57+
58+
<Button
59+
onClick
60+
color=(+ambient(Colors)).secondary
61+
text="SECONDARY COLOR" />
62+
63+
val outlinedShape = +withDensity {
64+
RoundedRectangleBorder(
65+
side = BorderSide(Color(0xFF888888.toInt())),
66+
// TODO(Andrey): Could shapes be more declarative, so we will copy
67+
// the current default shape and just apply a new border color and
68+
// not be forced to redefine the borderRadius as well?
69+
borderRadius = BorderRadius.circular(
70+
4.dp.toPx().value
71+
)
72+
)
73+
}
74+
<Button
75+
onClick
76+
color=Color.Transparent
77+
shape=outlinedShape
78+
text="OUTLINED" />
79+
80+
<Button onClick>
81+
<Padding padding=EdgeInsets(16.dp)>
82+
<Text text=TextSpan(text = "CUSTOM BUTTON!") />
83+
</Padding>
84+
</Button>
85+
86+
// TODO(Andrey): Disabled button has wrong bg and text color for now.
87+
// Need to figure out where will we store their styling. Not a part of
88+
// MaterialColors right now and specs are not clear about this.
89+
<Button enabled=false text="DISABLED. TODO" />
90+
</Column>
91+
</Center>
92+
</MaterialTheme>
93+
</CraneWrapper>
94+
}

‎samples/UiMaterialDemos/src/main/java/androidx/ui/material/demos/RippleDemo.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import androidx.ui.core.Text
2121
import androidx.ui.core.dp
2222
import androidx.ui.layout.Container
2323
import androidx.ui.layout.EdgeInsets
24-
import androidx.ui.material.H1
24+
import androidx.ui.material.Body1TextStyle
2525
import androidx.ui.material.MaterialTheme
2626
import androidx.ui.material.borders.BorderRadius
2727
import androidx.ui.material.borders.BorderSide
@@ -47,9 +47,9 @@ fun RippleDemo() {
4747
<Container>
4848
<BoundedRipple>
4949
<Container width=100.dp height=50.dp>
50-
<H1>
50+
<Body1TextStyle>
5151
<Text text=TextSpan(text = "inner") />
52-
</H1>
52+
</Body1TextStyle>
5353
</Container>
5454
</BoundedRipple>
5555
</Container>

‎samples/UiMaterialDemos/src/main/java/androidx/ui/material/demos/TextActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import android.app.Activity
2020
import android.os.Bundle
2121
import androidx.ui.core.CraneWrapper
2222
import androidx.ui.core.Text
23-
import androidx.ui.material.H1
23+
import androidx.ui.material.H1TextStyle
2424
import androidx.ui.material.MaterialTheme
2525
import androidx.ui.painting.Color
2626
import androidx.ui.painting.TextSpan
@@ -34,13 +34,13 @@ open class TextActivity : Activity() {
3434
setContent {
3535
<CraneWrapper>
3636
<MaterialTheme>
37-
<H1>
37+
<H1TextStyle>
3838
<Text text=TextSpan(
3939
text = "Hello",
4040
style=TextStyle(
4141
color = Color(0xFFFF0000.toInt())
4242
)) />
43-
</H1>
43+
</H1TextStyle>
4444
</MaterialTheme>
4545
</CraneWrapper> }
4646
}

‎samples/UiMaterialDemos/src/main/res/drawable/ripple.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
-->
1717

1818
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
19-
android:color="#3003DAC6">
19+
android:color="#306200EE">
2020
<item android:drawable="@drawable/ripple_shape" />
2121
<item android:id="@android:id/mask"
2222
android:drawable="@drawable/ripple_shape" />

‎ui/core/src/main/java/androidx/ui/painting/Color.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ class Color(colorValue: Int) {
243243
)
244244
}
245245
}
246+
247+
/**
248+
* Fully transparent color.
249+
*/
250+
val Transparent = Color(0)
246251
}
247252

248253
/**

‎ui/framework-adapter/src/main/java/androidx/ui/core/adapter/Semantics.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ fun Semantics(
5454
// hint: String? = null,
5555
// textDirection: TextDirection? = null,
5656
// sortKey: SemanticsSortKey? = null,
57-
testTag: String? = null
58-
// onTap: (() -> Unit)? = null,
57+
testTag: String? = null,
58+
onTap: (() -> Unit)? = null
5959
// onLongPress: (() -> Unit)? = null,
6060
// onScrollLeft: (() -> Unit)? = null,
6161
// onScrollRight: (() -> Unit)? = null,
@@ -96,7 +96,7 @@ fun Semantics(
9696
null, // textDirection,
9797
null, // sortKey,
9898
testTag, // testTag,
99-
null, // onTap,
99+
onTap, // onTap,
100100
null, // onLongPress,
101101
null, // onScrollLeft,
102102
null, // onScrollRight,

‎ui/framework/api/1.0.0-alpha01.txt

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,6 @@ package androidx.ui.core {
2323
property public androidx.ui.core.Density density;
2424
}
2525

26-
public final class CurrentTextStyle extends com.google.r4a.Component {
27-
ctor public CurrentTextStyle(kotlin.jvm.functions.Function1<? super androidx.ui.painting.TextStyle,kotlin.Unit> children);
28-
method public void compose();
29-
method public kotlin.jvm.functions.Function1<androidx.ui.painting.TextStyle,kotlin.Unit> getChildren();
30-
method public void setChildren(kotlin.jvm.functions.Function1<? super androidx.ui.painting.TextStyle,kotlin.Unit> p);
31-
}
32-
33-
public final class CurrentTextStyleProvider extends com.google.r4a.Component {
34-
ctor public CurrentTextStyleProvider(kotlin.jvm.functions.Function0<kotlin.Unit> children);
35-
method public void compose();
36-
method public kotlin.jvm.functions.Function0<kotlin.Unit> getChildren();
37-
method public androidx.ui.painting.TextStyle? getValue();
38-
method public void setChildren(kotlin.jvm.functions.Function0<kotlin.Unit> p);
39-
method public void setValue(androidx.ui.painting.TextStyle? p);
40-
property public final androidx.ui.painting.TextStyle? value;
41-
}
42-
4326
public final class Draw extends com.google.r4a.Component {
4427
ctor public Draw(kotlin.jvm.functions.Function3<? super androidx.ui.core.DensityReceiver,? super androidx.ui.painting.Canvas,? super androidx.ui.core.PxSize,kotlin.Unit> onPaint);
4528
method public void compose();
@@ -214,7 +197,9 @@ package androidx.ui.core {
214197

215198
public final class TextKt {
216199
ctor public TextKt();
200+
method public static void CurrentTextStyleProvider(androidx.ui.painting.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
217201
method public static void TextComposable(androidx.ui.painting.TextSpan text, androidx.ui.engine.text.TextAlign textAlign = TextAlign.START, androidx.ui.engine.text.TextDirection textDirection = TextDirection.LTR, boolean softWrap = true, androidx.ui.rendering.paragraph.TextOverflow overflow = TextOverflow.CLIP, float textScaleFactor = 1.0f, Integer? maxLines = null, androidx.ui.services.text_editing.TextSelection? selection = null);
202+
method public static com.google.r4a.Effect<androidx.ui.painting.TextStyle> currentTextStyle();
218203
}
219204

220205
public final class WrapperKt {

‎ui/framework/api/current.txt

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,6 @@ package androidx.ui.core {
2323
property public androidx.ui.core.Density density;
2424
}
2525

26-
public final class CurrentTextStyle extends com.google.r4a.Component {
27-
ctor public CurrentTextStyle(kotlin.jvm.functions.Function1<? super androidx.ui.painting.TextStyle,kotlin.Unit> children);
28-
method public void compose();
29-
method public kotlin.jvm.functions.Function1<androidx.ui.painting.TextStyle,kotlin.Unit> getChildren();
30-
method public void setChildren(kotlin.jvm.functions.Function1<? super androidx.ui.painting.TextStyle,kotlin.Unit> p);
31-
}
32-
33-
public final class CurrentTextStyleProvider extends com.google.r4a.Component {
34-
ctor public CurrentTextStyleProvider(kotlin.jvm.functions.Function0<kotlin.Unit> children);
35-
method public void compose();
36-
method public kotlin.jvm.functions.Function0<kotlin.Unit> getChildren();
37-
method public androidx.ui.painting.TextStyle? getValue();
38-
method public void setChildren(kotlin.jvm.functions.Function0<kotlin.Unit> p);
39-
method public void setValue(androidx.ui.painting.TextStyle? p);
40-
property public final androidx.ui.painting.TextStyle? value;
41-
}
42-
4326
public final class Draw extends com.google.r4a.Component {
4427
ctor public Draw(kotlin.jvm.functions.Function3<? super androidx.ui.core.DensityReceiver,? super androidx.ui.painting.Canvas,? super androidx.ui.core.PxSize,kotlin.Unit> onPaint);
4528
method public void compose();
@@ -214,7 +197,9 @@ package androidx.ui.core {
214197

215198
public final class TextKt {
216199
ctor public TextKt();
200+
method public static void CurrentTextStyleProvider(androidx.ui.painting.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> children);
217201
method public static void TextComposable(androidx.ui.painting.TextSpan text, androidx.ui.engine.text.TextAlign textAlign = TextAlign.START, androidx.ui.engine.text.TextDirection textDirection = TextDirection.LTR, boolean softWrap = true, androidx.ui.rendering.paragraph.TextOverflow overflow = TextOverflow.CLIP, float textScaleFactor = 1.0f, Integer? maxLines = null, androidx.ui.services.text_editing.TextSelection? selection = null);
202+
method public static com.google.r4a.Effect<androidx.ui.painting.TextStyle> currentTextStyle();
218203
}
219204

220205
public final class WrapperKt {

‎ui/framework/src/main/java/androidx/ui/core/Text.kt

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ import com.google.r4a.Ambient
2929
import com.google.r4a.Children
3030
import com.google.r4a.Component
3131
import com.google.r4a.Composable
32+
import com.google.r4a.ambient
3233
import com.google.r4a.composer
34+
import com.google.r4a.effectOf
3335

3436
/** The default selection color if none is specified. */
3537
private val DEFAULT_SELECTION_COLOR = Color(0x6633B5E5)
@@ -170,31 +172,18 @@ fun TextComposable(
170172
* components included in this component's children will be styled with this style unless
171173
* styled explicitly.
172174
*/
173-
// TODO(clara): Make this a function instead of a class when cross module is solved
174-
class CurrentTextStyleProvider(@Children var children: () -> Unit) : Component() {
175-
var value: TextStyle? = null
176-
177-
override fun compose() {
178-
<CurrentTextStyleAmbient.Consumer> style ->
179-
val mergedStyle = style.merge(value)
180-
<CurrentTextStyleAmbient.Provider value=mergedStyle>
181-
<children />
182-
</CurrentTextStyleAmbient.Provider>
183-
</CurrentTextStyleAmbient.Consumer>
184-
}
175+
fun CurrentTextStyleProvider(value: TextStyle, @Children children: () -> Unit) {
176+
<CurrentTextStyleAmbient.Consumer> style ->
177+
val mergedStyle = style.merge(value)
178+
<CurrentTextStyleAmbient.Provider value=mergedStyle>
179+
<children />
180+
</CurrentTextStyleAmbient.Provider>
181+
</CurrentTextStyleAmbient.Consumer>
185182
}
186183

187184
/**
188-
* This component is used to read the current value of the Text style ambient. Any [Text]
185+
* This effect is used to read the current value of the Text style ambient. Any [Text]
189186
* components included in this component's children will be styled with this style unless
190187
* styled explicitly.
191188
*/
192-
// TODO(clara): Make this a function instead of a class when cross module is solved
193-
class CurrentTextStyle(@Children var children: (style: TextStyle) -> Unit) : Component() {
194-
195-
override fun compose() {
196-
<CurrentTextStyleAmbient.Consumer> style ->
197-
<children style />
198-
</CurrentTextStyleAmbient.Consumer>
199-
}
200-
}
189+
fun currentTextStyle() = effectOf<TextStyle> { +ambient(CurrentTextStyleAmbient) }

‎ui/framework/src/main/java/androidx/ui/core/gesture/PressIndicatorGestureDetector.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616

1717
package androidx.ui.core.gesture
1818

19-
import androidx.ui.core.PointerInput
20-
import androidx.ui.core.PxPosition
2119
import androidx.ui.core.PointerEventPass
20+
import androidx.ui.core.PointerInput
2221
import androidx.ui.core.PointerInputChange
22+
import androidx.ui.core.PxPosition
2323
import androidx.ui.core.anyPositionChangeConsumed
2424
import androidx.ui.core.changedToDown
2525
import androidx.ui.core.changedToDownIgnoreConsumed

‎ui/material/api/1.0.0-alpha01.txt

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
// Signature format: 3.0
2+
package androidx.ui.baseui {
3+
4+
public final class ClickableKt {
5+
ctor public ClickableKt();
6+
method public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, boolean enabled = true, boolean consumeDownOnStart = false, kotlin.jvm.functions.Function0<kotlin.Unit> children);
7+
}
8+
9+
}
10+
211
package androidx.ui.baseui.selection {
312

413
public final class MutuallyExclusiveSetItemKt {
@@ -21,6 +30,12 @@ package androidx.ui.baseui.selection {
2130

2231
package androidx.ui.material {
2332

33+
public final class ButtonKt {
34+
ctor public ButtonKt();
35+
method public static void Button(kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, boolean enabled = true, androidx.ui.material.borders.ShapeBorder? shape = null, androidx.ui.painting.Color? color = null, androidx.ui.core.Dp elevation = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
36+
method public static void Button(String text, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, boolean enabled = true, androidx.ui.material.borders.ShapeBorder? shape = null, androidx.ui.painting.Color? color = null, androidx.ui.core.Dp elevation = 0.dp);
37+
}
38+
2439
public final class Checkbox extends com.google.r4a.Component {
2540
ctor public Checkbox();
2641
method public void compose();
@@ -72,24 +87,17 @@ package androidx.ui.material {
7287
method public androidx.ui.painting.Color getSurface();
7388
}
7489

75-
public final class MaterialTheme extends com.google.r4a.Component {
76-
ctor public MaterialTheme(kotlin.jvm.functions.Function0<kotlin.Unit> children);
77-
method public void compose();
78-
method public kotlin.jvm.functions.Function0<kotlin.Unit> getChildren();
79-
method public androidx.ui.material.MaterialColors getColors();
80-
method public androidx.ui.material.MaterialTypography getTypography();
81-
method public void setChildren(kotlin.jvm.functions.Function0<kotlin.Unit> p);
82-
method public void setColors(androidx.ui.material.MaterialColors p);
83-
method public void setTypography(androidx.ui.material.MaterialTypography p);
84-
property public final androidx.ui.material.MaterialColors colors;
85-
property public final androidx.ui.material.MaterialTypography typography;
86-
}
87-
8890
public final class MaterialThemeKt {
8991
ctor public MaterialThemeKt();
92+
method public static void MaterialButtonShapeTheme(kotlin.jvm.functions.Function0<kotlin.Unit> children);
9093
method public static void MaterialRippleTheme(kotlin.jvm.functions.Function0<kotlin.Unit> children);
94+
method public static void MaterialTheme(androidx.ui.material.MaterialColors colors = androidx.ui.material.MaterialColors(), androidx.ui.material.MaterialTypography typography = androidx.ui.material.MaterialTypography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
9195
method public static com.google.r4a.Ambient<androidx.ui.material.MaterialColors> getColors();
96+
method public static com.google.r4a.Ambient<androidx.ui.material.Shapes> getCurrentShapeAmbient();
9297
method public static com.google.r4a.Ambient<androidx.ui.material.MaterialTypography> getTypography();
98+
method public static com.google.r4a.Effect<androidx.ui.painting.Color> orFromTheme(androidx.ui.painting.Color?, kotlin.jvm.functions.Function1<? super androidx.ui.material.MaterialColors,androidx.ui.painting.Color> choosingBlock);
99+
method public static com.google.r4a.Effect<androidx.ui.material.borders.ShapeBorder> orFromTheme(androidx.ui.material.borders.ShapeBorder?, kotlin.jvm.functions.Function1<? super androidx.ui.material.Shapes,? extends androidx.ui.material.borders.ShapeBorder> choosingBlock);
100+
method @CheckResult("+") public static com.google.r4a.Effect<androidx.ui.painting.TextStyle> themeTextStyle(kotlin.jvm.functions.Function1<? super androidx.ui.material.MaterialTypography,androidx.ui.painting.TextStyle> choosingBlock);
93101
}
94102

95103
public final class MaterialTypography {
@@ -135,14 +143,26 @@ package androidx.ui.material {
135143
method public void RadioTextItem(boolean isSelected, String text, androidx.ui.core.Dp labelOffset = androidx.ui.material.RadioButtonKt.DefaultRadioLabelOffset, androidx.ui.painting.Color? radioColor = null, androidx.ui.painting.TextStyle? textStyle = null);
136144
}
137145

146+
public final class Shapes {
147+
ctor public Shapes(androidx.ui.material.borders.ShapeBorder button);
148+
method public androidx.ui.material.borders.ShapeBorder component1();
149+
method public androidx.ui.material.Shapes copy(androidx.ui.material.borders.ShapeBorder button);
150+
method public androidx.ui.material.borders.ShapeBorder getButton();
151+
}
152+
138153
public final class SwitchKt {
139154
ctor public SwitchKt();
140155
method public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onChecked = null, androidx.ui.painting.Color? color = null);
141156
}
142157

143158
public final class TextKt {
144159
ctor public TextKt();
145-
method public static void H1(kotlin.jvm.functions.Function0<kotlin.Unit> content);
160+
method public static void Body1TextStyle(kotlin.jvm.functions.Function0<kotlin.Unit> children);
161+
method public static void ButtonTextStyle(kotlin.jvm.functions.Function0<kotlin.Unit> children);
162+
method public static void H1TextStyle(kotlin.jvm.functions.Function0<kotlin.Unit> children);
163+
method public static void TextColor(kotlin.jvm.functions.Function1<? super androidx.ui.material.MaterialColors,androidx.ui.painting.Color> color, kotlin.jvm.functions.Function0<kotlin.Unit> children);
164+
method public static void TextColorForBackground(androidx.ui.painting.Color background, kotlin.jvm.functions.Function0<kotlin.Unit> children);
165+
method public static com.google.r4a.Effect<androidx.ui.painting.Color> textColorForBackground(androidx.ui.painting.Color background);
146166
}
147167

148168
}
@@ -267,11 +287,13 @@ package androidx.ui.material.borders {
267287
ctor public CircleBorder();
268288
method public androidx.ui.material.borders.BorderSide component1();
269289
method public androidx.ui.material.borders.CircleBorder copy(androidx.ui.material.borders.BorderSide side);
290+
method public androidx.ui.material.borders.BorderStyle getBorderStyle();
270291
method public androidx.ui.painting.Path getInnerPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
271292
method public androidx.ui.painting.Path getOuterPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
272293
method public androidx.ui.material.borders.BorderSide getSide();
273294
method public void paint(androidx.ui.painting.Canvas canvas, androidx.ui.core.Density density, androidx.ui.engine.geometry.Rect rect, androidx.ui.engine.text.TextDirection? textDirection);
274295
method public androidx.ui.material.borders.CircleBorder scale(float t);
296+
property public androidx.ui.material.borders.BorderStyle borderStyle;
275297
}
276298

277299
public final class RoundedRectangleBorder extends androidx.ui.material.borders.ShapeBorder {
@@ -281,23 +303,27 @@ package androidx.ui.material.borders {
281303
method public androidx.ui.material.borders.BorderRadius component2();
282304
method public androidx.ui.material.borders.RoundedRectangleBorder copy(androidx.ui.material.borders.BorderSide side, androidx.ui.material.borders.BorderRadius borderRadius);
283305
method public androidx.ui.material.borders.BorderRadius getBorderRadius();
306+
method public androidx.ui.material.borders.BorderStyle getBorderStyle();
284307
method public androidx.ui.painting.Path getInnerPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
285308
method public androidx.ui.painting.Path getOuterPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
286309
method public androidx.ui.material.borders.BorderSide getSide();
287310
method public void paint(androidx.ui.painting.Canvas canvas, androidx.ui.core.Density density, androidx.ui.engine.geometry.Rect rect, androidx.ui.engine.text.TextDirection? textDirection);
288311
method public androidx.ui.material.borders.ShapeBorder scale(float t);
312+
property public androidx.ui.material.borders.BorderStyle borderStyle;
289313
}
290314

291315
public abstract class ShapeBorder {
292316
ctor public ShapeBorder();
293317
method protected androidx.ui.material.borders.ShapeBorder? add(androidx.ui.material.borders.ShapeBorder other, boolean reversed = false);
318+
method public abstract androidx.ui.material.borders.BorderStyle getBorderStyle();
294319
method public abstract androidx.ui.painting.Path getInnerPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection = null);
295320
method public abstract androidx.ui.painting.Path getOuterPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection = null);
296321
method public androidx.ui.material.borders.ShapeBorder? lerpFrom(androidx.ui.material.borders.ShapeBorder? a, float t);
297322
method public androidx.ui.material.borders.ShapeBorder? lerpTo(androidx.ui.material.borders.ShapeBorder? b, float t);
298323
method public abstract void paint(androidx.ui.painting.Canvas canvas, androidx.ui.core.Density density, androidx.ui.engine.geometry.Rect rect, androidx.ui.engine.text.TextDirection? textDirection = null);
299324
method public final operator androidx.ui.material.borders.ShapeBorder plus(androidx.ui.material.borders.ShapeBorder other);
300325
method public abstract androidx.ui.material.borders.ShapeBorder scale(float t);
326+
property public abstract androidx.ui.material.borders.BorderStyle borderStyle;
301327
}
302328

303329
public final class ShapeBorderKt {

‎ui/material/api/current.txt

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
// Signature format: 3.0
2+
package androidx.ui.baseui {
3+
4+
public final class ClickableKt {
5+
ctor public ClickableKt();
6+
method public static void Clickable(kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, boolean enabled = true, boolean consumeDownOnStart = false, kotlin.jvm.functions.Function0<kotlin.Unit> children);
7+
}
8+
9+
}
10+
211
package androidx.ui.baseui.selection {
312

413
public final class MutuallyExclusiveSetItemKt {
@@ -21,6 +30,12 @@ package androidx.ui.baseui.selection {
2130

2231
package androidx.ui.material {
2332

33+
public final class ButtonKt {
34+
ctor public ButtonKt();
35+
method public static void Button(kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, boolean enabled = true, androidx.ui.material.borders.ShapeBorder? shape = null, androidx.ui.painting.Color? color = null, androidx.ui.core.Dp elevation = 0.dp, kotlin.jvm.functions.Function0<kotlin.Unit> children);
36+
method public static void Button(String text, kotlin.jvm.functions.Function0<kotlin.Unit>? onClick = null, boolean enabled = true, androidx.ui.material.borders.ShapeBorder? shape = null, androidx.ui.painting.Color? color = null, androidx.ui.core.Dp elevation = 0.dp);
37+
}
38+
2439
public final class Checkbox extends com.google.r4a.Component {
2540
ctor public Checkbox();
2641
method public void compose();
@@ -72,24 +87,17 @@ package androidx.ui.material {
7287
method public androidx.ui.painting.Color getSurface();
7388
}
7489

75-
public final class MaterialTheme extends com.google.r4a.Component {
76-
ctor public MaterialTheme(kotlin.jvm.functions.Function0<kotlin.Unit> children);
77-
method public void compose();
78-
method public kotlin.jvm.functions.Function0<kotlin.Unit> getChildren();
79-
method public androidx.ui.material.MaterialColors getColors();
80-
method public androidx.ui.material.MaterialTypography getTypography();
81-
method public void setChildren(kotlin.jvm.functions.Function0<kotlin.Unit> p);
82-
method public void setColors(androidx.ui.material.MaterialColors p);
83-
method public void setTypography(androidx.ui.material.MaterialTypography p);
84-
property public final androidx.ui.material.MaterialColors colors;
85-
property public final androidx.ui.material.MaterialTypography typography;
86-
}
87-
8890
public final class MaterialThemeKt {
8991
ctor public MaterialThemeKt();
92+
method public static void MaterialButtonShapeTheme(kotlin.jvm.functions.Function0<kotlin.Unit> children);
9093
method public static void MaterialRippleTheme(kotlin.jvm.functions.Function0<kotlin.Unit> children);
94+
method public static void MaterialTheme(androidx.ui.material.MaterialColors colors = androidx.ui.material.MaterialColors(), androidx.ui.material.MaterialTypography typography = androidx.ui.material.MaterialTypography(), kotlin.jvm.functions.Function0<kotlin.Unit> children);
9195
method public static com.google.r4a.Ambient<androidx.ui.material.MaterialColors> getColors();
96+
method public static com.google.r4a.Ambient<androidx.ui.material.Shapes> getCurrentShapeAmbient();
9297
method public static com.google.r4a.Ambient<androidx.ui.material.MaterialTypography> getTypography();
98+
method public static com.google.r4a.Effect<androidx.ui.painting.Color> orFromTheme(androidx.ui.painting.Color?, kotlin.jvm.functions.Function1<? super androidx.ui.material.MaterialColors,androidx.ui.painting.Color> choosingBlock);
99+
method public static com.google.r4a.Effect<androidx.ui.material.borders.ShapeBorder> orFromTheme(androidx.ui.material.borders.ShapeBorder?, kotlin.jvm.functions.Function1<? super androidx.ui.material.Shapes,? extends androidx.ui.material.borders.ShapeBorder> choosingBlock);
100+
method @CheckResult("+") public static com.google.r4a.Effect<androidx.ui.painting.TextStyle> themeTextStyle(kotlin.jvm.functions.Function1<? super androidx.ui.material.MaterialTypography,androidx.ui.painting.TextStyle> choosingBlock);
93101
}
94102

95103
public final class MaterialTypography {
@@ -135,14 +143,26 @@ package androidx.ui.material {
135143
method public void RadioTextItem(boolean isSelected, String text, androidx.ui.core.Dp labelOffset = androidx.ui.material.RadioButtonKt.DefaultRadioLabelOffset, androidx.ui.painting.Color? radioColor = null, androidx.ui.painting.TextStyle? textStyle = null);
136144
}
137145

146+
public final class Shapes {
147+
ctor public Shapes(androidx.ui.material.borders.ShapeBorder button);
148+
method public androidx.ui.material.borders.ShapeBorder component1();
149+
method public androidx.ui.material.Shapes copy(androidx.ui.material.borders.ShapeBorder button);
150+
method public androidx.ui.material.borders.ShapeBorder getButton();
151+
}
152+
138153
public final class SwitchKt {
139154
ctor public SwitchKt();
140155
method public static void Switch(boolean checked, kotlin.jvm.functions.Function1<? super java.lang.Boolean,kotlin.Unit>? onChecked = null, androidx.ui.painting.Color? color = null);
141156
}
142157

143158
public final class TextKt {
144159
ctor public TextKt();
145-
method public static void H1(kotlin.jvm.functions.Function0<kotlin.Unit> content);
160+
method public static void Body1TextStyle(kotlin.jvm.functions.Function0<kotlin.Unit> children);
161+
method public static void ButtonTextStyle(kotlin.jvm.functions.Function0<kotlin.Unit> children);
162+
method public static void H1TextStyle(kotlin.jvm.functions.Function0<kotlin.Unit> children);
163+
method public static void TextColor(kotlin.jvm.functions.Function1<? super androidx.ui.material.MaterialColors,androidx.ui.painting.Color> color, kotlin.jvm.functions.Function0<kotlin.Unit> children);
164+
method public static void TextColorForBackground(androidx.ui.painting.Color background, kotlin.jvm.functions.Function0<kotlin.Unit> children);
165+
method public static com.google.r4a.Effect<androidx.ui.painting.Color> textColorForBackground(androidx.ui.painting.Color background);
146166
}
147167

148168
}
@@ -267,11 +287,13 @@ package androidx.ui.material.borders {
267287
ctor public CircleBorder();
268288
method public androidx.ui.material.borders.BorderSide component1();
269289
method public androidx.ui.material.borders.CircleBorder copy(androidx.ui.material.borders.BorderSide side);
290+
method public androidx.ui.material.borders.BorderStyle getBorderStyle();
270291
method public androidx.ui.painting.Path getInnerPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
271292
method public androidx.ui.painting.Path getOuterPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
272293
method public androidx.ui.material.borders.BorderSide getSide();
273294
method public void paint(androidx.ui.painting.Canvas canvas, androidx.ui.core.Density density, androidx.ui.engine.geometry.Rect rect, androidx.ui.engine.text.TextDirection? textDirection);
274295
method public androidx.ui.material.borders.CircleBorder scale(float t);
296+
property public androidx.ui.material.borders.BorderStyle borderStyle;
275297
}
276298

277299
public final class RoundedRectangleBorder extends androidx.ui.material.borders.ShapeBorder {
@@ -281,23 +303,27 @@ package androidx.ui.material.borders {
281303
method public androidx.ui.material.borders.BorderRadius component2();
282304
method public androidx.ui.material.borders.RoundedRectangleBorder copy(androidx.ui.material.borders.BorderSide side, androidx.ui.material.borders.BorderRadius borderRadius);
283305
method public androidx.ui.material.borders.BorderRadius getBorderRadius();
306+
method public androidx.ui.material.borders.BorderStyle getBorderStyle();
284307
method public androidx.ui.painting.Path getInnerPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
285308
method public androidx.ui.painting.Path getOuterPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection);
286309
method public androidx.ui.material.borders.BorderSide getSide();
287310
method public void paint(androidx.ui.painting.Canvas canvas, androidx.ui.core.Density density, androidx.ui.engine.geometry.Rect rect, androidx.ui.engine.text.TextDirection? textDirection);
288311
method public androidx.ui.material.borders.ShapeBorder scale(float t);
312+
property public androidx.ui.material.borders.BorderStyle borderStyle;
289313
}
290314

291315
public abstract class ShapeBorder {
292316
ctor public ShapeBorder();
293317
method protected androidx.ui.material.borders.ShapeBorder? add(androidx.ui.material.borders.ShapeBorder other, boolean reversed = false);
318+
method public abstract androidx.ui.material.borders.BorderStyle getBorderStyle();
294319
method public abstract androidx.ui.painting.Path getInnerPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection = null);
295320
method public abstract androidx.ui.painting.Path getOuterPath(androidx.ui.engine.geometry.Rect rect, androidx.ui.core.Density density, androidx.ui.engine.text.TextDirection? textDirection = null);
296321
method public androidx.ui.material.borders.ShapeBorder? lerpFrom(androidx.ui.material.borders.ShapeBorder? a, float t);
297322
method public androidx.ui.material.borders.ShapeBorder? lerpTo(androidx.ui.material.borders.ShapeBorder? b, float t);
298323
method public abstract void paint(androidx.ui.painting.Canvas canvas, androidx.ui.core.Density density, androidx.ui.engine.geometry.Rect rect, androidx.ui.engine.text.TextDirection? textDirection = null);
299324
method public final operator androidx.ui.material.borders.ShapeBorder plus(androidx.ui.material.borders.ShapeBorder other);
300325
method public abstract androidx.ui.material.borders.ShapeBorder scale(float t);
326+
property public abstract androidx.ui.material.borders.BorderStyle borderStyle;
301327
}
302328

303329
public final class ShapeBorderKt {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2019 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package androidx.ui.baseui
18+
19+
import androidx.ui.core.Layout
20+
import androidx.ui.core.adapter.Semantics
21+
import androidx.ui.core.gesture.PressReleasedGestureDetector
22+
import com.google.r4a.Children
23+
import com.google.r4a.Composable
24+
import com.google.r4a.composer
25+
26+
/**
27+
* Combines [PressReleasedGestureDetector] and [Semantics] for the clickable
28+
* components like Button.
29+
*/
30+
@Composable
31+
fun Clickable(
32+
/**
33+
* Will be called when user clicked on the children [Layout]
34+
*/
35+
onClick: (() -> Unit)? = null,
36+
/**
37+
* Defines the enabled state.
38+
* The children [Layout] will not be clickable when it set to false or when [onClick] is null.
39+
*/
40+
enabled: Boolean = true,
41+
/**
42+
* Should [PressReleasedGestureDetector] consume down events. You shouldn't if you have
43+
* some visual feedback like Ripples, as it will consume this events instead.
44+
*/
45+
consumeDownOnStart: Boolean = false,
46+
@Children children: () -> Unit
47+
) {
48+
<Semantics
49+
button=true
50+
enabled=enabled
51+
onTap=onClick>
52+
<PressReleasedGestureDetector
53+
onRelease=if (enabled) onClick else null
54+
consumeDownOnStart>
55+
<children />
56+
</PressReleasedGestureDetector>
57+
</Semantics>
58+
}
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*
2+
* Copyright 2019 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package androidx.ui.material
18+
19+
import androidx.ui.baseui.Clickable
20+
import androidx.ui.core.CurrentTextStyleProvider
21+
import androidx.ui.core.Dp
22+
import androidx.ui.core.IntPx
23+
import androidx.ui.core.Layout
24+
import androidx.ui.core.Text
25+
import androidx.ui.core.coerceAtLeast
26+
import androidx.ui.core.coerceAtMost
27+
import androidx.ui.core.dp
28+
import androidx.ui.material.borders.BorderStyle
29+
import androidx.ui.material.borders.ShapeBorder
30+
import androidx.ui.material.ripple.BoundedRipple
31+
import androidx.ui.material.surface.Surface
32+
import androidx.ui.painting.Color
33+
import androidx.ui.painting.TextSpan
34+
import com.google.r4a.Children
35+
import com.google.r4a.Composable
36+
import com.google.r4a.composer
37+
import com.google.r4a.unaryPlus
38+
39+
/**
40+
* [Button] with flexible user interface. You can provide any content you want as a
41+
* [children] composable.
42+
*
43+
* To make a [Button] clickable, you must provide an [onClick]. Setting [enabled] to false
44+
* also affects this state.
45+
* You can specify a [shape] of the surface, it's background [color] and an [elevation].
46+
*
47+
* The text style for internal [Text] components will be changed to [MaterialTypography.button],
48+
* text color will try to match the correlated color for the background [color]. For example,
49+
* on [MaterialColors.primary] background [MaterialColors.onPrimary] will be used for text.
50+
* To modify these default style values, use [CurrentTextStyleProvider].
51+
*
52+
* Example:
53+
* <Button onClick={ ... }>
54+
* <Padding padding=EdgeInsets(16.dp)>
55+
* <Text text=TextSpan(text = "CUSTOM BUTTON") />
56+
* </Padding>
57+
* </Button>
58+
*
59+
* @see Button overload for the default Material Design implementation of [Button] with text.
60+
*/
61+
@Composable
62+
fun Button(
63+
/**
64+
* Will be called when user clicked on the button
65+
*/
66+
onClick: (() -> Unit)? = null,
67+
/**
68+
* Defines the enabled state.
69+
* The button will not be clickable when it set to false or when [onClick] is null.
70+
*/
71+
enabled: Boolean = true,
72+
/**
73+
* Defines the Button's shape as well its shadow.
74+
*
75+
* When null is provided it uses the [Shapes.button] from [CurrentShapeAmbient].
76+
*/
77+
shape: ShapeBorder? = null,
78+
/**
79+
* The background color.
80+
*
81+
* When null is provided it uses the [MaterialColors.primary] color.
82+
*/
83+
color: Color? = null,
84+
/**
85+
* The z-coordinate at which to place this button. This controls the size
86+
* of the shadow below the button.
87+
*/
88+
elevation: Dp = 0.dp,
89+
@Children children: () -> Unit
90+
) {
91+
val surfaceColor = +color.orFromTheme { primary }
92+
val surfaceShape = +shape.orFromTheme { button }
93+
val clickableChildren = @Composable {
94+
<Clickable enabled onClick>
95+
<children />
96+
</Clickable>
97+
}
98+
<ButtonTextStyle>
99+
<TextColorForBackground background=surfaceColor>
100+
<Surface shape=surfaceShape color=surfaceColor elevation>
101+
if (enabled && onClick != null) {
102+
<BoundedRipple>
103+
<clickableChildren />
104+
</BoundedRipple>
105+
} else {
106+
<clickableChildren />
107+
}
108+
</Surface>
109+
</TextColorForBackground>
110+
</ButtonTextStyle>
111+
}
112+
113+
/**
114+
* Material Design implementation of [Button] with [text].
115+
*
116+
* [Button] will be clickable if you provide [onClick] and [enabled] set to true.
117+
* You can specify a [shape] of the surface, it's background [color] and [elevation].
118+
*
119+
* The text style for internal [Text] components will be changed to [MaterialTypography.button],
120+
* text color will try to match the correlated color for the background [color]. For example,
121+
* on [MaterialColors.primary] background [MaterialColors.onPrimary] will be used for text.
122+
*
123+
* Example:
124+
* <Button
125+
* onClick={ ... }
126+
* text="TEXT") />
127+
*
128+
* @see Button for the flexible implementation with a customizable content.
129+
*/
130+
@Composable
131+
fun Button(
132+
/**
133+
* The text to display.
134+
*/
135+
text: String,
136+
/**
137+
* Will be called when user clicked on the button
138+
*/
139+
onClick: (() -> Unit)? = null,
140+
/**
141+
* Defines the enabled state.
142+
* The button will not be clickable when it set to false or when [onClick] is null.
143+
*/
144+
enabled: Boolean = true,
145+
/**
146+
* Defines the Button's shape as well its shadow.
147+
*
148+
* When null is provided it uses the [Shapes.button] from [CurrentShapeAmbient].
149+
*/
150+
shape: ShapeBorder? = null,
151+
/**
152+
* The background color.
153+
*
154+
* When null is provided it uses the [MaterialColors.primary] color.
155+
*/
156+
color: Color? = null,
157+
/**
158+
* The z-coordinate at which to place this button. This controls the size
159+
* of the shadow below the button.
160+
*/
161+
elevation: Dp = 0.dp
162+
) {
163+
val surfaceColor = +color.orFromTheme { primary }
164+
val surfaceShape = +shape.orFromTheme { button }
165+
val hasBackground = surfaceColor.alpha > 0 || surfaceShape.borderStyle != BorderStyle.None
166+
val horPaddings = if (hasBackground) ButtonHorPadding else ButtonHorPaddingNoBg
167+
<Button onClick enabled elevation color=surfaceColor shape=surfaceShape >
168+
<Layout layoutBlock={ measurables, constraints ->
169+
val fullHorPaddings = horPaddings.toIntPx() * 2
170+
val textConstraints = constraints.copy(
171+
minWidth = (constraints.minWidth - fullHorPaddings).coerceAtLeast(IntPx.Zero),
172+
maxWidth = (constraints.maxWidth - fullHorPaddings).coerceAtLeast(IntPx.Zero),
173+
maxHeight = constraints.maxHeight.coerceAtMost(ButtonHeight.toIntPx())
174+
)
175+
176+
val placeable = measurables.first().measure(textConstraints)
177+
178+
val width =
179+
(placeable.width + fullHorPaddings).coerceAtLeast(ButtonMinWidth.toIntPx())
180+
val height = ButtonHeight.toIntPx()
181+
182+
val leftOffset = (width - fullHorPaddings - placeable.width) / 2 + fullHorPaddings / 2
183+
val topOffset = (height - placeable.height) / 2
184+
185+
layout(width, height) {
186+
placeable.place(leftOffset, topOffset)
187+
}
188+
}>
189+
<Text text=TextSpan(text = text) />
190+
</Layout>
191+
</Button>
192+
}
193+
194+
// Specification for Material Button:
195+
private val ButtonHeight = 36.dp
196+
private val ButtonMinWidth = 64.dp
197+
private val ButtonHorPadding = 16.dp
198+
private val ButtonHorPaddingNoBg = 8.dp

‎ui/material/src/main/java/androidx/ui/material/MaterialTheme.kt

Lines changed: 130 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@
1616

1717
package androidx.ui.material
1818

19+
import androidx.annotation.CheckResult
1920
import androidx.ui.core.CurrentTextStyleProvider
21+
import androidx.ui.core.dp
22+
import androidx.ui.core.withDensity
2023
import androidx.ui.engine.text.FontWeight
2124
import androidx.ui.engine.text.font.FontFamily
25+
import androidx.ui.material.borders.BorderRadius
26+
import androidx.ui.material.borders.RoundedRectangleBorder
27+
import androidx.ui.material.borders.ShapeBorder
2228
import androidx.ui.material.ripple.CurrentRippleTheme
2329
import androidx.ui.material.ripple.DefaultRippleEffectFactory
2430
import androidx.ui.material.ripple.RippleTheme
@@ -27,9 +33,12 @@ import androidx.ui.painting.TextStyle
2733
import androidx.ui.painting.withAlphaPercent
2834
import com.google.r4a.Ambient
2935
import com.google.r4a.Children
30-
import com.google.r4a.Component
3136
import com.google.r4a.Composable
37+
import com.google.r4a.Effect
38+
import com.google.r4a.ambient
3239
import com.google.r4a.composer
40+
import com.google.r4a.effectOf
41+
import com.google.r4a.unaryPlus
3342

3443
/**
3544
* This Component defines the styling principles from the Material design specification. It must be
@@ -44,25 +53,23 @@ import com.google.r4a.composer
4453
* All values may be overriden by providing this component with the [colors] and [typography]
4554
* attributes. Use this to configure the overall theme of your application.
4655
*/
47-
class MaterialTheme(
56+
fun MaterialTheme(
57+
colors: MaterialColors = MaterialColors(),
58+
typography: MaterialTypography = MaterialTypography(),
4859
@Children
49-
var children: () -> Unit
50-
) : Component() {
51-
52-
var colors: MaterialColors = MaterialColors()
53-
var typography: MaterialTypography = MaterialTypography()
54-
55-
override fun compose() {
56-
<Colors.Provider value=colors>
57-
<Typography.Provider value=typography>
58-
<CurrentTextStyleProvider value=typography.body1>
59-
<MaterialRippleTheme>
60+
children: () -> Unit
61+
) {
62+
<Colors.Provider value=colors>
63+
<Typography.Provider value=typography>
64+
<CurrentTextStyleProvider value=typography.body1>
65+
<MaterialRippleTheme>
66+
<MaterialButtonShapeTheme>
6067
<children />
61-
</MaterialRippleTheme>
62-
</CurrentTextStyleProvider>
63-
</Typography.Provider>
64-
</Colors.Provider>
65-
}
68+
</MaterialButtonShapeTheme>
69+
</MaterialRippleTheme>
70+
</CurrentTextStyleProvider>
71+
</Typography.Provider>
72+
</Colors.Provider>
6673
}
6774

6875
/**
@@ -77,8 +84,8 @@ val Colors = Ambient<MaterialColors>("colors") { error("No colors found!") }
7784
* This Ambient holds on to the current definiton of typography for this application as described
7885
* by the Material spec. You can read the values in it when creating custom components that want
7986
* to use Material types, as well as override the values when you want to re-style a part of your
80-
* hierarchy. Material components related to text such as [H1] will refer to this Ambient to obtain
81-
* the values with which to style text.
87+
* hierarchy. Material components related to text such as [H1TextStyle] will refer to this Ambient
88+
* to obtain the values with which to style text.
8289
*/
8390
val Typography = Ambient<MaterialTypography>("typography") { error("No typography found!") }
8491

@@ -221,10 +228,11 @@ fun MaterialRippleTheme(@Children children: () -> Unit) {
221228
val defaultTheme = RippleTheme(
222229
factory = DefaultRippleEffectFactory,
223230
colorCallback = { background ->
224-
if (background == null || background.computeLuminance() >= 0.5) { // light bg
225-
materialColors.secondary.withAlphaPercent(16f) // 12 %
231+
if (background == null || background.alpha == 0 ||
232+
background.computeLuminance() >= 0.5) { // light bg
233+
materialColors.primary.withAlphaPercent(12f)
226234
} else { // dark bg
227-
Color(0xFFFFFFFF.toInt()).withAlphaPercent(24f) // 24 % of white
235+
Color(0xFFFFFFFF.toInt()).withAlphaPercent(24f)
228236
}
229237
}
230238
)
@@ -233,3 +241,102 @@ fun MaterialRippleTheme(@Children children: () -> Unit) {
233241
</CurrentRippleTheme.Provider>
234242
</Colors.Consumer>
235243
}
244+
245+
/**
246+
* Helps to resolve the [TextStyle] by applying [choosingBlock] for the current [Typography].
247+
*
248+
* If you specify [background] text color will try to match the correlated color. For example,
249+
* on [MaterialColors.primary] background [MaterialColors.onPrimary] will be used.
250+
* If matching is failed [fallbackTextColor] will be used.
251+
*/
252+
@CheckResult(suggest = "+")
253+
fun themeTextStyle(
254+
choosingBlock: MaterialTypography.() -> TextStyle
255+
) = effectOf<TextStyle> {
256+
var style = (+ambient(Typography)).choosingBlock()
257+
258+
// TODO Text is working with pixels, but we define our theme in dps, let's convert here for now.
259+
// b/127345041
260+
if (style.fontSize != null) {
261+
style = style.copy(fontSize = +withDensity { style.fontSize!!.dp.toPx().value })
262+
}
263+
264+
style
265+
}
266+
267+
/**
268+
* Helps to resolve the [Color]. It will take the current value of the value from
269+
* [Colors] by applying the [choosingBlock] block on it.
270+
*
271+
* Example:
272+
* val finalColor = +color.orFromTheme { primary }
273+
*/
274+
fun Color?.orFromTheme(choosingBlock: MaterialColors.() -> Color): Effect<Color> {
275+
val color = this
276+
return effectOf {
277+
if (color == null) {
278+
(+ambient(Colors)).choosingBlock()
279+
} else {
280+
color
281+
}
282+
}
283+
}
284+
285+
// Shapes
286+
287+
/**
288+
* Data class holding current shapes for common surfaces like Button or Card.
289+
*/
290+
// TODO(Andrey): should have small, medium, large components categories. b/129278276
291+
// See https://material.io/design/shape/applying-shape-to-ui.html#baseline-shape-values
292+
data class Shapes(
293+
/**
294+
* Shape used for [Button]
295+
*/
296+
val button: ShapeBorder
297+
// TODO(Andrey): Add shapes for Card, other surfaces? will see what we need.
298+
)
299+
300+
/**
301+
* Ambient used to specify the default shapes for the surfaces.
302+
*
303+
* @see [MaterialButtonShapeTheme] for the default Material Design value
304+
*/
305+
val CurrentShapeAmbient = Ambient.of<Shapes> {
306+
throw IllegalStateException("No default shapes provided.")
307+
}
308+
309+
/**
310+
* Applies the default [ShapeBorder]s for all the surfaces.
311+
*/
312+
@Composable
313+
fun MaterialButtonShapeTheme(@Children children: () -> Unit) {
314+
val value = +withDensity {
315+
Shapes(
316+
button = RoundedRectangleBorder(
317+
borderRadius = BorderRadius.circular(4.dp.toPx().value)
318+
)
319+
)
320+
}
321+
<CurrentShapeAmbient.Provider value>
322+
<children />
323+
</CurrentShapeAmbient.Provider>
324+
}
325+
326+
/**
327+
* Helps to resolve the [ShapeBorder]. It will take the current value of the value from
328+
* [CurrentShapeAmbient] if null was used.
329+
*
330+
* Example:
331+
* val surfaceShape = +shape.orFromTheme{ button }
332+
*/
333+
fun ShapeBorder?.orFromTheme(choosingBlock: Shapes.() -> ShapeBorder): Effect<ShapeBorder> {
334+
val shape = this
335+
return effectOf {
336+
if (shape == null) {
337+
(+ambient(CurrentShapeAmbient)).choosingBlock()
338+
} else {
339+
shape
340+
}
341+
}
342+
}

‎ui/material/src/main/java/androidx/ui/material/Text.kt

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,92 @@
1717
package androidx.ui.material
1818

1919
import androidx.ui.core.CurrentTextStyleProvider
20+
import androidx.ui.core.Text
21+
import androidx.ui.painting.Color
22+
import androidx.ui.painting.TextStyle
2023
import com.google.r4a.Children
2124
import com.google.r4a.Composable
25+
import com.google.r4a.ambient
2226
import com.google.r4a.composer
27+
import com.google.r4a.effectOf
28+
import com.google.r4a.unaryPlus
2329

30+
/**
31+
* Applies [MaterialTypography.h1] for children [Text] components.
32+
*/
33+
@Composable
34+
fun H1TextStyle(@Children children: () -> Unit) {
35+
<CurrentTextStyleProvider value=+themeTextStyle { h1 }>
36+
<children />
37+
</CurrentTextStyleProvider>
38+
}
39+
40+
/**
41+
* Applies [MaterialTypography.body1] for children [Text] components.
42+
*/
2443
@Composable
25-
fun H1(@Children content: () -> Unit) {
26-
<Typography.Consumer> typography ->
27-
<CurrentTextStyleProvider value=typography.h1>
28-
<content />
29-
</CurrentTextStyleProvider>
30-
</Typography.Consumer>
44+
fun Body1TextStyle(@Children children: () -> Unit) {
45+
<CurrentTextStyleProvider value=+themeTextStyle { body1 }>
46+
<children />
47+
</CurrentTextStyleProvider>
3148
}
49+
50+
/**
51+
* Applies [MaterialTypography.button] for children [Text] components.
52+
*/
53+
@Composable
54+
fun ButtonTextStyle(@Children children: () -> Unit) {
55+
<CurrentTextStyleProvider value=+themeTextStyle { button }>
56+
<children />
57+
</CurrentTextStyleProvider>
58+
}
59+
60+
/**
61+
* Applies color for children [Text] components.
62+
*/
63+
@Composable
64+
fun TextColor(
65+
color: (MaterialColors.() -> Color),
66+
@Children children: () -> Unit
67+
) {
68+
val value = TextStyle(color = (+ambient(Colors)).color())
69+
<CurrentTextStyleProvider value>
70+
<children />
71+
</CurrentTextStyleProvider>
72+
}
73+
74+
/**
75+
* Applies color for children [Text] components.
76+
*
77+
* Tries to match the background color to correlated text color. For example,
78+
* on [MaterialColors.primary] background [MaterialColors.onPrimary] will be used.
79+
*
80+
* @see textColorForBackground
81+
*/
82+
@Composable
83+
fun TextColorForBackground(
84+
background: Color,
85+
@Children children: () -> Unit
86+
) {
87+
val value = TextStyle(color = +textColorForBackground(background))
88+
<CurrentTextStyleProvider value>
89+
<children />
90+
</CurrentTextStyleProvider>
91+
}
92+
93+
/**
94+
* Tries to match the background color to correlated text color. For example,
95+
* on [MaterialColors.primary] background [MaterialColors.onPrimary] will be used.
96+
*/
97+
fun textColorForBackground(background: Color) = effectOf<Color?> {
98+
with(+ambient(Colors)) {
99+
when (background) {
100+
primary -> onPrimary
101+
secondary -> onSecondary
102+
background -> onBackground
103+
surface -> onSurface
104+
error -> onError
105+
else -> primary
106+
}
107+
}
108+
}

‎ui/material/src/main/java/androidx/ui/material/borders/CircleBorder.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ data class CircleBorder(
4444
val side: BorderSide = BorderSide.None
4545
) : ShapeBorder() {
4646

47+
override val borderStyle: BorderStyle
48+
get() = side.style
49+
4750
// TODO("Migration|Andrey: Needs EdgeInsetsGeometry")
4851
// @override
4952
// EdgeInsetsGeometry get dimensions {

‎ui/material/src/main/java/androidx/ui/material/borders/RoundedRectangleBorder.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ data class RoundedRectangleBorder(
4949
val borderRadius: BorderRadius = BorderRadius.Zero
5050
) : ShapeBorder() {
5151

52+
override val borderStyle: BorderStyle
53+
get() = side.style
54+
5255
// TODO("Migration|Andrey: Needs EdgeInsetsGeometry")
5356
// @override
5457
// EdgeInsetsGeometry get dimensions {
@@ -147,6 +150,9 @@ private data class RoundedRectangleToCircleBorder(
147150
val borderRadius: BorderRadius = BorderRadius.Zero
148151
) : ShapeBorder() {
149152

153+
override val borderStyle: BorderStyle
154+
get() = side.style
155+
150156
// TODO("Migration|Andrey: Needs EdgeInsetsGeometry")
151157
// @override
152158
// EdgeInsetsGeometry get dimensions {

‎ui/material/src/main/java/androidx/ui/material/borders/ShapeBorder.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ abstract class ShapeBorder {
235235
rect: Rect,
236236
textDirection: TextDirection? = null
237237
)
238+
239+
// TODO(Andrey) Investigate how to make it better. b/129278276
240+
abstract val borderStyle: BorderStyle
238241
}
239242

240243
/**

‎ui/material/src/main/java/androidx/ui/material/surface/Surface.kt

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@
1717
package androidx.ui.material.surface
1818

1919
import androidx.ui.core.Dp
20-
import androidx.ui.core.IntPx
2120
import androidx.ui.core.Layout
2221
import androidx.ui.core.dp
23-
import androidx.ui.core.hasBoundedHeight
24-
import androidx.ui.core.hasBoundedWidth
22+
import androidx.ui.core.ipx
2523
import androidx.ui.material.borders.RoundedRectangleBorder
2624
import androidx.ui.material.borders.ShapeBorder
2725
import androidx.ui.material.clip.ClipPath
@@ -107,27 +105,24 @@ fun Surface(
107105

108106
/**
109107
* A simple MeasureBox which just reserves a space for a [Surface].
110-
* It position the children in the left top corner and takes all the available space.
108+
* It position the only child in the left top corner.
111109
*
112110
* TODO("Andrey: Should be replaced with some basic layout implementation when we have it")
113111
*/
114112
@Composable
115-
internal fun SurfaceMeasureBox(@Children children: () -> Unit) {
116-
<Layout layoutBlock = { measurables, constraints ->
117-
val width = if (constraints.hasBoundedWidth) {
118-
constraints.maxWidth
119-
} else {
120-
constraints.minWidth
113+
private fun SurfaceMeasureBox(@Children children: () -> Unit) {
114+
<Layout children layoutBlock={ measurables, constraints ->
115+
if (measurables.size > 1) {
116+
throw IllegalStateException("Surface can have only one direct measurable child!")
121117
}
122-
123-
val height = if (constraints.hasBoundedHeight) {
124-
constraints.maxHeight
118+
val measurable = measurables.firstOrNull()
119+
if (measurable == null) {
120+
layout(constraints.minWidth, constraints.minHeight) {}
125121
} else {
126-
constraints.minHeight
127-
}
128-
129-
layout(width, height) {
130-
measurables.forEach { it.measure(constraints).place(IntPx.Zero, IntPx.Zero) }
122+
val placeable = measurable.measure(constraints)
123+
layout(placeable.width, placeable.height) {
124+
placeable.place(0.ipx, 0.ipx)
125+
}
131126
}
132-
} children />
127+
} />
133128
}

0 commit comments

Comments
 (0)
Please sign in to comment.