[go: nahoru, domu]

blob: 06e41d06377a4cd2505c3bd4b23c4f0246ea39bd [file] [log] [blame]
/*
* Copyright 2022 The Android Open Source Project
*
* 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.
*/
package androidx.wear.tiles.material.layouts;
import static androidx.wear.tiles.DimensionBuilders.dp;
import static androidx.wear.tiles.DimensionBuilders.expand;
import static androidx.wear.tiles.material.Helper.checkNotNull;
import static androidx.wear.tiles.material.ProgressIndicatorDefaults.DEFAULT_PADDING;
import static androidx.wear.tiles.material.layouts.LayoutDefaults.PROGRESS_INDICATOR_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP;
import static androidx.wear.tiles.material.layouts.LayoutDefaults.PROGRESS_INDICATOR_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.wear.tiles.DeviceParametersBuilders;
import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters;
import androidx.wear.tiles.DimensionBuilders.DpProp;
import androidx.wear.tiles.LayoutElementBuilders;
import androidx.wear.tiles.LayoutElementBuilders.Box;
import androidx.wear.tiles.LayoutElementBuilders.Layout;
import androidx.wear.tiles.LayoutElementBuilders.LayoutElement;
import androidx.wear.tiles.ModifiersBuilders.Modifiers;
import androidx.wear.tiles.ModifiersBuilders.Padding;
import androidx.wear.tiles.TimelineBuilders.Timeline;
import androidx.wear.tiles.TimelineBuilders.TimelineEntry;
import androidx.wear.tiles.material.CircularProgressIndicator;
import androidx.wear.tiles.proto.LayoutElementProto;
/**
* Tiles layout that represents the suggested layout style for Material Tiles with the progress
* indicator around the edges of the screen and the given content inside of it and the recommended
* margin and padding applied.
*/
// TODO(b/215323986): Link visuals.
public class ProgressIndicatorLayout implements LayoutElement {
@NonNull private final LayoutElement mElement;
ProgressIndicatorLayout(@NonNull LayoutElement layoutElement) {
this.mElement = layoutElement;
}
/** Builder class for {@link ProgressIndicatorLayout}. */
public static final class Builder implements LayoutElement.Builder {
@NonNull private final DeviceParameters mDeviceParameters;
@Nullable private LayoutElement mProgressIndicator = null;
@Nullable private LayoutElement mContent = null;
/**
* Creates a builder for the {@link ProgressIndicatorLayout}t. Custom content inside of it
* can later be set with ({@link #setContent}.
*/
public Builder(@NonNull DeviceParameters deviceParameters) {
this.mDeviceParameters = deviceParameters;
}
/** Sets the progress indicator which will be around the edges. */
@NonNull
// There is no direct matching getter for this setter as the serialized format of the
// ProtoLayouts do not allow for a direct reconstruction of the arguments. Instead there are
// methods to get the contents a whole for rendering.
@SuppressWarnings("MissingGetterMatchingBuilder")
public Builder setProgressIndicatorContent(@NonNull LayoutElement progressIndicator) {
this.mProgressIndicator = progressIndicator;
return this;
}
/** Sets the additional content to this layout, inside of the screen. */
@NonNull
public Builder setContent(@NonNull LayoutElement content) {
this.mContent = content;
return this;
}
private boolean isRoundDevice() {
return mDeviceParameters.getScreenShape()
== DeviceParametersBuilders.SCREEN_SHAPE_ROUND;
}
/**
* Constructs and returns {@link ProgressIndicatorLayout} with the provided content and
* look.
*/
@NonNull
@Override
public ProgressIndicatorLayout build() {
float thicknessDp =
mProgressIndicator instanceof CircularProgressIndicator
? ((CircularProgressIndicator) mProgressIndicator)
.getStrokeWidth()
.getValue()
: 0;
float horizontalPaddingDp =
isRoundDevice()
? PROGRESS_INDICATOR_LAYOUT_MARGIN_HORIZONTAL_ROUND_DP
: PROGRESS_INDICATOR_LAYOUT_MARGIN_HORIZONTAL_SQUARE_DP;
float indicatorWidth = 2 * (thicknessDp + DEFAULT_PADDING.getValue());
float mainContentHeightDp = mDeviceParameters.getScreenHeightDp() - indicatorWidth;
float mainContentWidthDp = mDeviceParameters.getScreenWidthDp() - indicatorWidth;
DpProp mainContentHeight = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
DpProp mainContentWidth = dp(Math.min(mainContentHeightDp, mainContentWidthDp));
Modifiers modifiers =
new Modifiers.Builder()
.setPadding(
new Padding.Builder()
.setStart(dp(horizontalPaddingDp))
.setEnd(dp(horizontalPaddingDp))
.build())
.build();
Box.Builder boxBuilder =
new Box.Builder()
.setWidth(expand())
.setHeight(expand())
.setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
.setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER);
if (mContent != null) {
boxBuilder.addContent(
new Box.Builder()
.setModifiers(modifiers)
.setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
.setHorizontalAlignment(
LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
.setHeight(mainContentHeight)
.setWidth(mainContentWidth)
.addContent(mContent)
.build());
}
if (mProgressIndicator != null) {
boxBuilder.addContent(mProgressIndicator);
}
return new ProgressIndicatorLayout(boxBuilder.build());
}
}
/** Returns the {@link Layout} object containing this layout template. */
@NonNull
public Layout toLayout() {
return toLayoutBuilder().build();
}
/** Returns the {@link Layout.Builder} object containing this layout template. */
@NonNull
public Layout.Builder toLayoutBuilder() {
return new Layout.Builder().setRoot(mElement);
}
/** Returns the {@link TimelineEntry.Builder} object containing this layout template. */
@NonNull
public TimelineEntry.Builder toTimelineEntryBuilder() {
return new TimelineEntry.Builder().setLayout(toLayout());
}
/** Returns the {@link TimelineEntry} object containing this layout template. */
@NonNull
public TimelineEntry toTimelineEntry() {
return toTimelineEntryBuilder().build();
}
/** Returns the {@link Timeline.Builder} object containing this layout template. */
@NonNull
public Timeline.Builder toTimelineBuilder() {
return new Timeline.Builder().addTimelineEntry(toTimelineEntry());
}
/** Returns the {@link Timeline} object containing this layout template. */
@NonNull
public Timeline toTimeline() {
return toTimelineBuilder().build();
}
/** Get the inner content from this layout. */
@NonNull
public LayoutElement getContent() {
return checkNotNull(((Box) ((Box) mElement).getContents().get(0)).getContents().get(0));
}
/** @hide */
@NonNull
@Override
@RestrictTo(Scope.LIBRARY_GROUP)
public LayoutElementProto.LayoutElement toLayoutElementProto() {
return mElement.toLayoutElementProto();
}
}