public class

Button

extends java.lang.Object

implements LayoutElementBuilders.LayoutElement

 java.lang.Object

↳androidx.wear.tiles.material.Button

Gradle dependencies

compile group: 'androidx.wear.tiles', name: 'tiles-material', version: '1.4.0'

  • groupId: androidx.wear.tiles
  • artifactId: tiles-material
  • version: 1.4.0

Artifact androidx.wear.tiles:tiles-material:1.4.0 it located at Google repository (https://maven.google.com/)

Overview

Tiles component Button that represents clickable button with the given content.

The Button is circular in shape. The recommended sizes are defined in ButtonDefaults.

The recommended set of ButtonColors styles can be obtained from ButtonDefaults., e.g. ButtonDefaults.PRIMARY_COLORS to get a color scheme for a primary Button.

When accessing the contents of a container for testing, note that this element can't be simply casted back to the original type, i.e.:

 Button button = new Button...
 Box box = new Box.Builder().addContent(button).build();

 Button myButton = (Button) box.getContents().get(0);
 
will fail.

To be able to get Button object from any layout element, Button.fromLayoutElement(LayoutElementBuilders.LayoutElement) method should be used, i.e.:

 Button myButton = Button.fromLayoutElement(box.getContents().get(0));
 

Summary

Methods
public static ButtonfromLayoutElement(LayoutElementBuilders.LayoutElement element)

Returns Button object from the given androidx.wear.tiles.LayoutElementBuilders.LayoutElement (e.g.

public ButtonColorsgetButtonColors()

Returns button color of this Button.

public ModifiersBuilders.ClickablegetClickable()

Returns click event action associated with this Button.

public java.lang.CharSequencegetContentDescription()

Returns content description for this Button.

public LayoutElementBuilders.LayoutElementgetCustomContent()

Returns the custom content of this Button if it has been added.

public FingerprintgetFingerprint()

public java.lang.StringgetIconContent()

Returns the icon content of this Button if it has been added.

public java.lang.StringgetImageContent()

Returns the image content of this Button if it has been added.

public DimensionBuilders.ContainerDimensiongetSize()

Returns size for this Button.

public java.lang.StringgetTextContent()

Returns the text content of this Button if it has been added.

public LayoutElementProto.LayoutElementtoLayoutElementProto()

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Methods

public LayoutElementBuilders.LayoutElement getCustomContent()

Returns the custom content of this Button if it has been added. Otherwise, it returns null.

public java.lang.String getIconContent()

Returns the icon content of this Button if it has been added. Otherwise, it returns null.

public java.lang.String getImageContent()

Returns the image content of this Button if it has been added. Otherwise, it returns null.

public java.lang.String getTextContent()

Returns the text content of this Button if it has been added. Otherwise, it returns null.

public ModifiersBuilders.Clickable getClickable()

Returns click event action associated with this Button.

public java.lang.CharSequence getContentDescription()

Returns content description for this Button.

Returns size for this Button.

public ButtonColors getButtonColors()

Returns button color of this Button.

public static Button fromLayoutElement(LayoutElementBuilders.LayoutElement element)

Returns Button object from the given androidx.wear.tiles.LayoutElementBuilders.LayoutElement (e.g. one retrieved from a container's content with container.getContents().get(index)) if that element can be converted to Button. Otherwise, it will return null.

public LayoutElementProto.LayoutElement toLayoutElementProto()

public Fingerprint getFingerprint()

Source

/*
 * Copyright 2021 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;

import static androidx.annotation.Dimension.DP;

import android.content.Context;

import androidx.annotation.Dimension;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.RestrictTo.Scope;
import androidx.wear.protolayout.expression.Fingerprint;
import androidx.wear.protolayout.proto.LayoutElementProto;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;

/**
 * Tiles component {@link Button} that represents clickable button with the given content.
 *
 * <p>The Button is circular in shape. The recommended sizes are defined in {@link ButtonDefaults}.
 *
 * <p>The recommended set of {@link ButtonColors} styles can be obtained from {@link
 * ButtonDefaults}., e.g. {@link ButtonDefaults#PRIMARY_COLORS} to get a color scheme for a primary
 * {@link Button}.
 *
 * <p>When accessing the contents of a container for testing, note that this element can't be simply
 * casted back to the original type, i.e.:
 *
 * <pre>{@code
 * Button button = new Button...
 * Box box = new Box.Builder().addContent(button).build();
 *
 * Button myButton = (Button) box.getContents().get(0);
 * }</pre>
 *
 * will fail.
 *
 * <p>To be able to get {@link Button} object from any layout element, {@link #fromLayoutElement}
 * method should be used, i.e.:
 *
 * <pre>{@code
 * Button myButton = Button.fromLayoutElement(box.getContents().get(0));
 * }</pre>
 *
 * @deprecated Use the new class {@link androidx.wear.protolayout.material.Button} which provides
 *     the same API and functionality.
 */
@Deprecated
@SuppressWarnings("deprecation")
public class Button implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement {
    /**
     * Tool tag for Metadata in androidx.wear.tiles.ModifiersBuilders.Modifiers, so we know that
     * androidx.wear.tiles.LayoutElementBuilders.Box is actually a Button with text.
     */
    static final String METADATA_TAG_TEXT = "TXTBTN";

    /**
     * Tool tag for Metadata in androidx.wear.tiles.ModifiersBuilders.Modifiers, so we know that
     * androidx.wear.tiles.LayoutElementBuilders.Box is actually a Button with icon.
     */
    static final String METADATA_TAG_ICON = "ICNBTN";

    /**
     * Tool tag for Metadata in androidx.wear.tiles.ModifiersBuilders.Modifiers, so we know that
     * androidx.wear.tiles.LayoutElementBuilders.Box is actually a Button with image.
     */
    static final String METADATA_TAG_IMAGE = "IMGBTN";

    /**
     * Tool tag for Metadata in androidx.wear.tiles.ModifiersBuilders.Modifiers, so we know that
     * androidx.wear.tiles.LayoutElementBuilders.Box is actually a Button with custom content.
     */
    static final String METADATA_TAG_CUSTOM_CONTENT = "CSTBTN";

    @NonNull private final androidx.wear.tiles.LayoutElementBuilders.Box mElement;

    Button(@NonNull androidx.wear.tiles.LayoutElementBuilders.Box element) {
        mElement = element;
    }

    /** Builder class for {@link Button}. */
    public static final class Builder
            implements androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder {
        private static final int NOT_SET = -1;
        private static final int ICON = 0;
        private static final int TEXT = 1;
        private static final int IMAGE = 2;
        private static final int CUSTOM_CONTENT = 3;

        @NonNull static final Map<Integer, String> TYPE_TO_TAG = new HashMap<>();

        @RestrictTo(RestrictTo.Scope.LIBRARY)
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({NOT_SET, ICON, TEXT, IMAGE, CUSTOM_CONTENT})
        @interface ButtonType {}

        @NonNull private final Context mContext;
        @Nullable private androidx.wear.tiles.LayoutElementBuilders.LayoutElement mCustomContent;
        @NonNull private final androidx.wear.tiles.ModifiersBuilders.Clickable mClickable;
        @NonNull private CharSequence mContentDescription = "";

        @NonNull
        private androidx.wear.tiles.DimensionBuilders.DpProp mSize = ButtonDefaults.DEFAULT_SIZE;

        @Nullable private String mText = null;
        @Nullable private Integer mTypographyName = null;
        @Nullable private String mIcon = null;
        @Nullable private androidx.wear.tiles.DimensionBuilders.DpProp mIconSize = null;
        @Nullable private String mImage = null;
        @NonNull private ButtonColors mButtonColors = ButtonDefaults.PRIMARY_COLORS;
        @ButtonType private int mType = NOT_SET;

        static {
            TYPE_TO_TAG.put(ICON, METADATA_TAG_ICON);
            TYPE_TO_TAG.put(TEXT, METADATA_TAG_TEXT);
            TYPE_TO_TAG.put(IMAGE, METADATA_TAG_IMAGE);
            TYPE_TO_TAG.put(CUSTOM_CONTENT, METADATA_TAG_CUSTOM_CONTENT);
        }

        /**
         * Creates a builder for the {@link Button} from the given content. Custom content should be
         * later set with one of the following ({@link #setIconContent}, {@link #setTextContent},
         * {@link #setImageContent}.
         *
         * @param context The application's context.
         * @param clickable Associated {@link androidx.wear.tiles.ModifiersBuilders.Clickable} for
         *     click events. When the Button is clicked it will fire the associated action.
         */
        public Builder(
                @NonNull Context context,
                @NonNull androidx.wear.tiles.ModifiersBuilders.Clickable clickable) {
            mClickable = clickable;
            mContext = context;
        }

        /**
         * Sets the content description for the {@link Button}. It is highly recommended to provide
         * this for button containing icon or image.
         */
        @NonNull
        public Builder setContentDescription(@NonNull CharSequence contentDescription) {
            this.mContentDescription = contentDescription;
            return this;
        }

        /**
         * Sets the size for the {@link Button}. Strongly recommended values are {@link
         * ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and {@link
         * ButtonDefaults#EXTRA_LARGE_SIZE}. If not set, {@link ButtonDefaults#DEFAULT_SIZE} will be
         * used.
         */
        @NonNull
        public Builder setSize(@NonNull androidx.wear.tiles.DimensionBuilders.DpProp size) {
            mSize = size;
            return this;
        }

        /**
         * Sets the size for the {@link Button}. Strongly recommended values are {@link
         * ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and {@link
         * ButtonDefaults#EXTRA_LARGE_SIZE}. If not set, {@link ButtonDefaults#DEFAULT_SIZE} will be
         * used.
         */
        @NonNull
        public Builder setSize(@Dimension(unit = DP) float size) {
            mSize = androidx.wear.tiles.DimensionBuilders.dp(size);
            return this;
        }

        /**
         * Sets the colors for the {@link Button}. If not set, {@link ButtonDefaults#PRIMARY_COLORS}
         * will be used.
         */
        @NonNull
        public Builder setButtonColors(@NonNull ButtonColors buttonColors) {
            mButtonColors = buttonColors;
            return this;
        }

        /**
         * Sets the custom content for this Button. Any previously added content will be overridden.
         */
        @NonNull
        public Builder setCustomContent(
                @NonNull androidx.wear.tiles.LayoutElementBuilders.LayoutElement content) {
            resetContent();
            this.mCustomContent = content;
            this.mType = CUSTOM_CONTENT;
            return this;
        }

        /**
         * Sets the content of this Button to be the given icon with the given size. Any previously
         * added content will be overridden. Provided icon will be tinted to the given content color
         * from {@link ButtonColors} and with the given size. This icon should be image with chosen
         * alpha channel and not an actual image.
         */
        @NonNull
        public Builder setIconContent(
                @NonNull String imageResourceId,
                @NonNull androidx.wear.tiles.DimensionBuilders.DpProp size) {
            resetContent();
            this.mIcon = imageResourceId;
            this.mType = ICON;
            this.mIconSize = size;
            return this;
        }

        /**
         * Sets the content of this Button to be the given icon with the default size that is half
         * of the set size of the button. Any previously added content will be overridden. Provided
         * icon will be tinted to the given content color from {@link ButtonColors}. This icon
         * should be image with chosen alpha channel and not an actual image.
         */
        @NonNull
        public Builder setIconContent(@NonNull String imageResourceId) {
            resetContent();
            this.mIcon = imageResourceId;
            this.mType = ICON;
            return this;
        }

        /**
         * Sets the content of this Button to be the given text with the default font for the set
         * size (for the {@link ButtonDefaults#DEFAULT_SIZE}, {@link ButtonDefaults#LARGE_SIZE} and
         * {@link ButtonDefaults#EXTRA_LARGE_SIZE} is {@link Typography#TYPOGRAPHY_TITLE2}, {@link
         * Typography#TYPOGRAPHY_TITLE1} and {@link Typography#TYPOGRAPHY_DISPLAY3} respectively).
         * Any previously added content will be overridden. Text should contain no more than 3
         * characters, otherwise it will overflow from the edges.
         */
        @NonNull
        public Builder setTextContent(@NonNull String text) {
            resetContent();
            this.mText = text;
            this.mType = TEXT;
            return this;
        }

        /**
         * Sets the content of this Button to be the given text with the given font. If you need
         * more font related customization, consider using {@link #setCustomContent} with {@link
         * Text} component. Any previously added content will be overridden. Text should contain no
         * more than 3 characters, otherwise it will overflow from the edges.
         */
        @NonNull
        public Builder setTextContent(
                @NonNull String text, @Typography.TypographyName int typographyName) {
            resetContent();
            this.mText = text;
            this.mTypographyName = typographyName;
            this.mType = TEXT;
            return this;
        }

        /**
         * Sets the content of this Button to be the given image, i.e. contacts photo. Any
         * previously added content will be overridden.
         */
        @NonNull
        public Builder setImageContent(@NonNull String imageResourceId) {
            resetContent();
            this.mImage = imageResourceId;
            this.mType = IMAGE;
            return this;
        }

        private void resetContent() {
            this.mText = null;
            this.mTypographyName = null;
            this.mIcon = null;
            this.mImage = null;
            this.mCustomContent = null;
            this.mIconSize = null;
        }

        /** Constructs and returns {@link Button} with the provided field and look. */
        @NonNull
        @Override
        public Button build() {
            androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder modifiers =
                    new androidx.wear.tiles.ModifiersBuilders.Modifiers.Builder()
                            .setClickable(mClickable)
                            .setBackground(
                                    new androidx.wear.tiles.ModifiersBuilders.Background.Builder()
                                            .setColor(mButtonColors.getBackgroundColor())
                                            .setCorner(
                                                    new androidx.wear.tiles.ModifiersBuilders.Corner
                                                                    .Builder()
                                                            .setRadius(Helper.radiusOf(mSize))
                                                            .build())
                                            .build())
                            .setMetadata(
                                    new androidx.wear.tiles.ModifiersBuilders.ElementMetadata
                                                    .Builder()
                                            .setTagData(
                                                    Helper.getTagBytes(
                                                            Helper.checkNotNull(
                                                                    TYPE_TO_TAG.get(mType))))
                                            .build());
            if (mContentDescription.length() > 0) {
                modifiers.setSemantics(
                        new androidx.wear.tiles.ModifiersBuilders.Semantics.Builder()
                                .setContentDescription(mContentDescription.toString())
                                .build());
            }

            androidx.wear.tiles.LayoutElementBuilders.Box.Builder element =
                    new androidx.wear.tiles.LayoutElementBuilders.Box.Builder()
                            .setHeight(mSize)
                            .setWidth(mSize)
                            .setModifiers(modifiers.build());

            element.addContent(getCorrectContent());

            return new Button(element.build());
        }

        @NonNull
        private androidx.wear.tiles.LayoutElementBuilders.LayoutElement getCorrectContent() {
            androidx.wear.tiles.LayoutElementBuilders.LayoutElement.Builder content;
            switch (mType) {
                case ICON:
                    {
                        androidx.wear.tiles.DimensionBuilders.DpProp iconSize =
                                mIconSize != null
                                        ? mIconSize
                                        : ButtonDefaults.recommendedIconSize(mSize);
                        content =
                                new androidx.wear.tiles.LayoutElementBuilders.Image.Builder()
                                        .setResourceId(Helper.checkNotNull(mIcon))
                                        .setHeight(Helper.checkNotNull(iconSize))
                                        .setWidth(iconSize)
                                        .setContentScaleMode(
                                                androidx.wear.tiles.LayoutElementBuilders
                                                        .CONTENT_SCALE_MODE_FILL_BOUNDS)
                                        .setColorFilter(
                                                new androidx.wear.tiles.LayoutElementBuilders
                                                                .ColorFilter.Builder()
                                                        .setTint(mButtonColors.getContentColor())
                                                        .build());

                        return content.build();
                    }
                case TEXT:
                    {
                        @Typography.TypographyName
                        int typographyName =
                                mTypographyName != null
                                        ? mTypographyName
                                        : getDefaultTypographyForSize(mSize);
                        content =
                                new Text.Builder(mContext, Helper.checkNotNull(mText))
                                        .setMaxLines(1)
                                        .setTypography(typographyName)
                                        .setColor(mButtonColors.getContentColor());

                        return content.build();
                    }
                case IMAGE:
                    {
                        content =
                                new androidx.wear.tiles.LayoutElementBuilders.Image.Builder()
                                        .setResourceId(Helper.checkNotNull(mImage))
                                        .setHeight(mSize)
                                        .setWidth(mSize)
                                        .setContentScaleMode(
                                                androidx.wear.tiles.LayoutElementBuilders
                                                        .CONTENT_SCALE_MODE_FILL_BOUNDS);
                        return content.build();
                    }
                case CUSTOM_CONTENT:
                    return Helper.checkNotNull(mCustomContent);
                case NOT_SET:
                    // Shouldn't happen.
                default:
                    // Shouldn't happen.
                    throw new IllegalArgumentException("Wrong Button type");
            }
        }

        private static @Typography.TypographyName int getDefaultTypographyForSize(
                @NonNull androidx.wear.tiles.DimensionBuilders.DpProp size) {
            if (size.getValue() == ButtonDefaults.LARGE_SIZE.getValue()) {
                return Typography.TYPOGRAPHY_TITLE1;
            } else if (size.getValue() == ButtonDefaults.EXTRA_LARGE_SIZE.getValue()) {
                return Typography.TYPOGRAPHY_DISPLAY3;
            } else {
                return Typography.TYPOGRAPHY_TITLE2;
            }
        }
    }

    /**
     * Returns the custom content of this Button if it has been added. Otherwise, it returns null.
     */
    @Nullable
    public androidx.wear.tiles.LayoutElementBuilders.LayoutElement getCustomContent() {
        if (!getMetadataTag().equals(METADATA_TAG_CUSTOM_CONTENT)) {
            return null;
        }
        return getAnyContent();
    }

    /** Returns the icon content of this Button if it has been added. Otherwise, it returns null. */
    @Nullable
    public String getIconContent() {
        androidx.wear.tiles.LayoutElementBuilders.Image icon = getIconContentObject();
        return icon != null ? Helper.checkNotNull(icon.getResourceId()).getValue() : null;
    }

    /**
     * Returns the image content of this Button if it has been added. Otherwise, it returns null.
     */
    @Nullable
    public String getImageContent() {
        androidx.wear.tiles.LayoutElementBuilders.Image image = getImageContentObject();
        return image != null ? Helper.checkNotNull(image.getResourceId()).getValue() : null;
    }

    /** Returns the text content of this Button if it has been added. Otherwise, it returns null. */
    @Nullable
    public String getTextContent() {
        Text text = getTextContentObject();
        return text != null ? text.getText() : null;
    }

    @NonNull
    private androidx.wear.tiles.LayoutElementBuilders.LayoutElement getAnyContent() {
        return Helper.checkNotNull(mElement.getContents().get(0));
    }

    @Nullable
    private androidx.wear.tiles.LayoutElementBuilders.Image getIconContentObject() {
        if (!getMetadataTag().equals(METADATA_TAG_ICON)) {
            return null;
        }
        return (androidx.wear.tiles.LayoutElementBuilders.Image) getAnyContent();
    }

    @Nullable
    private Text getTextContentObject() {
        if (!getMetadataTag().equals(METADATA_TAG_TEXT)) {
            return null;
        }
        return Text.fromLayoutElement(getAnyContent());
    }

    @Nullable
    private androidx.wear.tiles.LayoutElementBuilders.Image getImageContentObject() {
        if (!getMetadataTag().equals(METADATA_TAG_IMAGE)) {
            return null;
        }
        return (androidx.wear.tiles.LayoutElementBuilders.Image) getAnyContent();
    }

    /** Returns click event action associated with this Button. */
    @NonNull
    public androidx.wear.tiles.ModifiersBuilders.Clickable getClickable() {
        return Helper.checkNotNull(Helper.checkNotNull(mElement.getModifiers()).getClickable());
    }

    /** Returns content description for this Button. */
    @Nullable
    public CharSequence getContentDescription() {
        androidx.wear.tiles.ModifiersBuilders.Semantics semantics =
                Helper.checkNotNull(mElement.getModifiers()).getSemantics();
        if (semantics == null) {
            return null;
        }
        return semantics.getContentDescription();
    }

    /** Returns size for this Button. */
    @NonNull
    public androidx.wear.tiles.DimensionBuilders.ContainerDimension getSize() {
        return Helper.checkNotNull(mElement.getWidth());
    }

    private androidx.wear.tiles.ColorBuilders.ColorProp getBackgroundColor() {
        return Helper.checkNotNull(
                Helper.checkNotNull(Helper.checkNotNull(mElement.getModifiers()).getBackground())
                        .getColor());
    }

    /** Returns button color of this Button. */
    @NonNull
    public ButtonColors getButtonColors() {
        androidx.wear.tiles.ColorBuilders.ColorProp backgroundColor = getBackgroundColor();
        androidx.wear.tiles.ColorBuilders.ColorProp contentColor = null;

        switch (getMetadataTag()) {
            case METADATA_TAG_TEXT:
                contentColor = Helper.checkNotNull(getTextContentObject()).getColor();
                break;
            case METADATA_TAG_ICON:
                contentColor =
                        Helper.checkNotNull(
                                        Helper.checkNotNull(getIconContentObject())
                                                .getColorFilter())
                                .getTint();
                break;
            case METADATA_TAG_IMAGE:
                contentColor =
                        Helper.checkNotNull(
                                        Helper.checkNotNull(getImageContentObject())
                                                .getColorFilter())
                                .getTint();
                break;
            case METADATA_TAG_CUSTOM_CONTENT:
                break;
        }

        if (contentColor == null) {
            contentColor = new androidx.wear.tiles.ColorBuilders.ColorProp.Builder().build();
        }

        return new ButtonColors(backgroundColor, contentColor);
    }

    /** Returns metadata tag set to this Button. */
    @NonNull
    String getMetadataTag() {
        return Helper.getMetadataTagName(
                Helper.checkNotNull(Helper.checkNotNull(mElement.getModifiers()).getMetadata()));
    }

    /**
     * Returns Button object from the given androidx.wear.tiles.LayoutElementBuilders.LayoutElement
     * (e.g. one retrieved from a container's content with {@code
     * container.getContents().get(index)}) if that element can be converted to Button. Otherwise,
     * it will return null.
     */
    @Nullable
    public static Button fromLayoutElement(
            @NonNull androidx.wear.tiles.LayoutElementBuilders.LayoutElement element) {
        if (element instanceof Button) {
            return (Button) element;
        }
        if (!(element instanceof androidx.wear.tiles.LayoutElementBuilders.Box)) {
            return null;
        }
        androidx.wear.tiles.LayoutElementBuilders.Box boxElement =
                (androidx.wear.tiles.LayoutElementBuilders.Box) element;
        if (!Helper.checkTag(boxElement.getModifiers(), Builder.TYPE_TO_TAG.values())) {
            return null;
        }
        // Now we are sure that this element is a Button.
        return new Button(boxElement);
    }

    @NonNull
    @Override
    @RestrictTo(Scope.LIBRARY_GROUP)
    public LayoutElementProto.LayoutElement toLayoutElementProto() {
        return Helper.checkNotNull(mElement.toLayoutElementProto());
    }

    @RestrictTo(Scope.LIBRARY_GROUP)
    @Nullable
    @Override
    public Fingerprint getFingerprint() {
        return mElement.getFingerprint();
    }
}