public class

SliceStyle

extends java.lang.Object

 java.lang.Object

↳androidx.slice.widget.SliceStyle

Gradle dependencies

compile group: 'androidx.slice', name: 'slice-view', version: '1.1.0-alpha02'

  • groupId: androidx.slice
  • artifactId: slice-view
  • version: 1.1.0-alpha02

Artifact androidx.slice:slice-view:1.1.0-alpha02 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.slice:slice-view com.android.support:slices-view

Overview

Holds style information shared between child views of a slice

Summary

Constructors
publicSliceStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)

Methods
public booleangetApplyCornerRadiusToLargeImages()

public booleangetExpandToAvailableHeight()

public intgetGridBottomPadding()

public intgetGridHeight(GridContent grid, SliceViewPolicy policy)

public intgetGridSubtitleSize()

public intgetGridTitleSize()

public intgetGridTopPadding()

public intgetHeaderSubtitleSize()

public intgetHeaderTitleSize()

public booleangetHideHeaderRow()

public floatgetImageCornerRadius()

public intgetListHeight(ListContent list, SliceViewPolicy policy)

public androidx.slice.widget.DisplayedListItemsgetListItemsForNonScrollingList(ListContent list, int availableHeight, SliceViewPolicy policy)

Returns a list of items that can fit in the provided height.

public intgetListItemsHeight(java.util.List<SliceContent> listItems, SliceViewPolicy policy)

public java.util.List<SliceContent>getListItemsToDisplay(ListContent list)

Returns a list of items that should be displayed to the user.

public intgetRowHeight(RowContent row, SliceViewPolicy policy)

public intgetRowInlineRangeHeight()

public intgetRowMaxHeight()

public intgetRowMinHeight()

public intgetRowRangeHeight()

public intgetRowSelectionHeight()

public RowStylegetRowStyle(SliceItem sliceItem)

Returns the RowStyle to use for the given SliceItem.

public intgetSubtitleColor()

public intgetSubtitleSize()

public intgetTintColor()

public intgetTitleColor()

public intgetTitleSize()

public intgetVerticalGridTextPadding()

public intgetVerticalHeaderTextPadding()

public intgetVerticalTextPadding()

public voidsetRowStyleFactory(RowStyleFactory rowStyleFactory)

Sets the RowStyleFactory which allows multiple children to have different styles.

public voidsetTintColor(int tint)

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

Constructors

public SliceStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)

Methods

public int getRowMinHeight()

public int getRowMaxHeight()

public int getRowInlineRangeHeight()

public void setTintColor(int tint)

public int getTintColor()

public int getTitleColor()

public int getSubtitleColor()

public int getHeaderTitleSize()

public int getHeaderSubtitleSize()

public int getVerticalHeaderTextPadding()

public int getTitleSize()

public int getSubtitleSize()

public int getVerticalTextPadding()

public int getGridTitleSize()

public int getGridSubtitleSize()

public int getVerticalGridTextPadding()

public int getGridTopPadding()

public int getGridBottomPadding()

public RowStyle getRowStyle(SliceItem sliceItem)

Returns the RowStyle to use for the given SliceItem.

public void setRowStyleFactory(RowStyleFactory rowStyleFactory)

Sets the RowStyleFactory which allows multiple children to have different styles.

public int getRowRangeHeight()

public int getRowSelectionHeight()

public boolean getExpandToAvailableHeight()

public boolean getHideHeaderRow()

public boolean getApplyCornerRadiusToLargeImages()

public float getImageCornerRadius()

public int getRowHeight(RowContent row, SliceViewPolicy policy)

public int getGridHeight(GridContent grid, SliceViewPolicy policy)

public int getListHeight(ListContent list, SliceViewPolicy policy)

public int getListItemsHeight(java.util.List<SliceContent> listItems, SliceViewPolicy policy)

public androidx.slice.widget.DisplayedListItems getListItemsForNonScrollingList(ListContent list, int availableHeight, SliceViewPolicy policy)

Returns a list of items that can fit in the provided height. If this list has a see more item this will be displayed in the list if appropriate.

Parameters:

list: the list from which to source the items.
availableHeight: to use to determine the row items to return.
policy: the policy info (scrolling, mode) to use when determining row items to return.

Returns:

the list of items that can be displayed in the provided height.

public java.util.List<SliceContent> getListItemsToDisplay(ListContent list)

Returns a list of items that should be displayed to the user.

Parameters:

list: the list from which to source the items.

Source

/*
 * Copyright 2018 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.slice.widget;

import static androidx.slice.core.SliceHints.ICON_IMAGE;
import static androidx.slice.core.SliceHints.RAW_IMAGE_LARGE;
import static androidx.slice.core.SliceHints.UNKNOWN_IMAGE;
import static androidx.slice.widget.SliceView.MODE_LARGE;
import static androidx.slice.widget.SliceView.MODE_SMALL;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.slice.SliceItem;
import androidx.slice.view.R;

import java.util.ArrayList;
import java.util.List;

/**
 * Holds style information shared between child views of a slice
 *
 * @hide
 */
@RestrictTo(RestrictTo.Scope.LIBRARY)
@RequiresApi(19)
public class SliceStyle {
    private int mTintColor = -1;
    private final int mTitleColor;
    private final int mSubtitleColor;
    private final int mHeaderTitleSize;
    private final int mHeaderSubtitleSize;
    private final int mVerticalHeaderTextPadding;
    private final int mTitleSize;
    private final int mSubtitleSize;
    private final int mVerticalTextPadding;
    private final int mGridTitleSize;
    private final int mGridSubtitleSize;
    private final int mVerticalGridTextPadding;
    private final int mGridTopPadding;
    private final int mGridBottomPadding;

    private final int mRowMaxHeight;
    private final int mRowTextWithRangeHeight;
    private final int mRowSingleTextWithRangeHeight;
    private final int mRowMinHeight;
    private final int mRowRangeHeight;
    private final int mRowSelectionHeight;
    private final int mRowTextWithSelectionHeight;
    private final int mRowSingleTextWithSelectionHeight;
    private final int mRowInlineRangeHeight;

    private final int mGridBigPicMinHeight;
    private final int mGridBigPicMaxHeight;
    private final int mGridAllImagesHeight;
    private final int mGridImageTextHeight;
    private final int mGridRawImageTextHeight;
    private final int mGridMaxHeight;
    private final int mGridMinHeight;

    private final int mListMinScrollHeight;
    private final int mListLargeHeight;

    private final boolean mExpandToAvailableHeight;
    private final boolean mHideHeaderRow;

    private final int mDefaultRowStyleRes;
    private final SparseArray<RowStyle> mResourceToRowStyle = new SparseArray<>();
    private RowStyleFactory mRowStyleFactory;

    private final Context mContext;

    private final float mImageCornerRadius;

    public SliceStyle(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SliceView,
                defStyleAttr, defStyleRes);
        try {
            int themeColor = a.getColor(R.styleable.SliceView_tintColor, -1);
            mTintColor = themeColor != -1 ? themeColor : mTintColor;
            mTitleColor = a.getColor(R.styleable.SliceView_titleColor, 0);
            mSubtitleColor = a.getColor(R.styleable.SliceView_subtitleColor, 0);

            mHeaderTitleSize = (int) a.getDimension(
                    R.styleable.SliceView_headerTitleSize, 0);
            mHeaderSubtitleSize = (int) a.getDimension(
                    R.styleable.SliceView_headerSubtitleSize, 0);
            mVerticalHeaderTextPadding = (int) a.getDimension(
                    R.styleable.SliceView_headerTextVerticalPadding, 0);

            mTitleSize = (int) a.getDimension(R.styleable.SliceView_titleSize, 0);
            mSubtitleSize = (int) a.getDimension(
                    R.styleable.SliceView_subtitleSize, 0);
            mVerticalTextPadding = (int) a.getDimension(
                    R.styleable.SliceView_textVerticalPadding, 0);

            mGridTitleSize = (int) a.getDimension(R.styleable.SliceView_gridTitleSize, 0);
            mGridSubtitleSize = (int) a.getDimension(
                    R.styleable.SliceView_gridSubtitleSize, 0);
            int defaultVerticalGridPadding = context.getResources().getDimensionPixelSize(
                    R.dimen.abc_slice_grid_text_inner_padding);
            mVerticalGridTextPadding = (int) a.getDimension(
                    R.styleable.SliceView_gridTextVerticalPadding, defaultVerticalGridPadding);
            mGridTopPadding = (int) a.getDimension(R.styleable.SliceView_gridTopPadding, 0);
            mGridBottomPadding = (int) a.getDimension(R.styleable.SliceView_gridBottomPadding, 0);

            mDefaultRowStyleRes = a.getResourceId(R.styleable.SliceView_rowStyle, 0);

            int defaultRowMinHeight = context.getResources().getDimensionPixelSize(
                    R.dimen.abc_slice_row_min_height);
            mRowMinHeight = (int) a.getDimension(
                    R.styleable.SliceView_rowMinHeight, defaultRowMinHeight);

            int defaultRowMaxHeight = context.getResources().getDimensionPixelSize(
                    R.dimen.abc_slice_row_max_height);
            mRowMaxHeight = (int) a.getDimension(
                    R.styleable.SliceView_rowMaxHeight, defaultRowMaxHeight);

            int defaultRowRangeHeight = context.getResources().getDimensionPixelSize(
                    R.dimen.abc_slice_row_range_height);
            mRowRangeHeight = (int) a.getDimension(
                    R.styleable.SliceView_rowRangeHeight, defaultRowRangeHeight);

            int defaultRowSingleTextWithRangeHeight = context.getResources().getDimensionPixelSize(
                    R.dimen.abc_slice_row_range_single_text_height);
            mRowSingleTextWithRangeHeight = (int) a.getDimension(
                    R.styleable.SliceView_rowRangeSingleTextHeight,
                    defaultRowSingleTextWithRangeHeight);

            int defaultRowInlineRangeHeight = context.getResources().getDimensionPixelSize(
                    R.dimen.abc_slice_row_range_inline_height);
            mRowInlineRangeHeight = (int) a.getDimension(
                    R.styleable.SliceView_rowInlineRangeHeight, defaultRowInlineRangeHeight);

            mExpandToAvailableHeight = a.getBoolean(
                    R.styleable.SliceView_expandToAvailableHeight, false);

            mHideHeaderRow = a.getBoolean(R.styleable.SliceView_hideHeaderRow, false);

            mContext = context;

            mImageCornerRadius = a.getDimension(R.styleable.SliceView_imageCornerRadius, 0);
        } finally {
            a.recycle();
        }

        // Note: The above colors and dimensions are styleable, but the below ones are not.

        final Resources r = context.getResources();

        mRowTextWithRangeHeight = r.getDimensionPixelSize(
                R.dimen.abc_slice_row_range_multi_text_height);
        mRowSelectionHeight = r.getDimensionPixelSize(R.dimen.abc_slice_row_selection_height);
        mRowTextWithSelectionHeight = r.getDimensionPixelSize(
                R.dimen.abc_slice_row_selection_multi_text_height);
        mRowSingleTextWithSelectionHeight = r.getDimensionPixelSize(
                R.dimen.abc_slice_row_selection_single_text_height);

        mGridBigPicMinHeight = r.getDimensionPixelSize(R.dimen.abc_slice_big_pic_min_height);
        mGridBigPicMaxHeight = r.getDimensionPixelSize(R.dimen.abc_slice_big_pic_max_height);
        mGridAllImagesHeight = r.getDimensionPixelSize(R.dimen.abc_slice_grid_image_only_height);
        mGridImageTextHeight = r.getDimensionPixelSize(R.dimen.abc_slice_grid_image_text_height);
        mGridRawImageTextHeight = r.getDimensionPixelSize(
                R.dimen.abc_slice_grid_raw_image_text_offset);
        mGridMinHeight = r.getDimensionPixelSize(R.dimen.abc_slice_grid_min_height);
        mGridMaxHeight = r.getDimensionPixelSize(R.dimen.abc_slice_grid_max_height);

        mListMinScrollHeight = r.getDimensionPixelSize(R.dimen.abc_slice_row_min_height);
        mListLargeHeight = r.getDimensionPixelSize(R.dimen.abc_slice_large_height);
    }

    public int getRowMinHeight() {
        return mRowMinHeight;
    }

    public int getRowMaxHeight() {
        return mRowMaxHeight;
    }

    public int getRowInlineRangeHeight() {
        return mRowInlineRangeHeight;
    }

    public void setTintColor(int tint) {
        mTintColor = tint;
    }

    public int getTintColor() {
        return mTintColor;
    }

    public int getTitleColor() {
        return mTitleColor;
    }

    public int getSubtitleColor() {
        return mSubtitleColor;
    }

    public int getHeaderTitleSize() {
        return mHeaderTitleSize;
    }

    public int getHeaderSubtitleSize() {
        return mHeaderSubtitleSize;
    }

    public int getVerticalHeaderTextPadding() {
        return mVerticalHeaderTextPadding;
    }

    public int getTitleSize() {
        return mTitleSize;
    }

    public int getSubtitleSize() {
        return mSubtitleSize;
    }

    public int getVerticalTextPadding() {
        return mVerticalTextPadding;
    }

    public int getGridTitleSize() {
        return mGridTitleSize;
    }

    public int getGridSubtitleSize() {
        return mGridSubtitleSize;
    }

    public int getVerticalGridTextPadding() {
        return mVerticalGridTextPadding;
    }

    public int getGridTopPadding() {
        return mGridTopPadding;
    }

    public int getGridBottomPadding() {
        return mGridBottomPadding;
    }

    /**
     * Returns the {@link RowStyle} to use for the given {@link SliceItem}.
     */
    @NonNull
    public RowStyle getRowStyle(@Nullable SliceItem sliceItem) {
        int rowStyleRes = mDefaultRowStyleRes;

        if (sliceItem != null && mRowStyleFactory != null) {
            int maybeStyleRes = mRowStyleFactory.getRowStyleRes(sliceItem);
            if (maybeStyleRes != 0) {
                rowStyleRes = maybeStyleRes;
            }
        }

        if (rowStyleRes == 0) {
            // Return default values.
            return new RowStyle(mContext, this);
        }

        RowStyle rowStyle = mResourceToRowStyle.get(rowStyleRes);
        if (rowStyle == null) {
            rowStyle = new RowStyle(mContext, rowStyleRes, this);
            mResourceToRowStyle.put(rowStyleRes, rowStyle);
        }
        return rowStyle;
    }

    /**
     * Sets the {@link RowStyleFactory} which allows multiple children to have different styles.
     */
    public void setRowStyleFactory(@Nullable RowStyleFactory rowStyleFactory) {
        mRowStyleFactory = rowStyleFactory;
    }

    public int getRowRangeHeight() {
        return mRowRangeHeight;
    }

    public int getRowSelectionHeight() {
        return mRowSelectionHeight;
    }

    public boolean getExpandToAvailableHeight() {
        return mExpandToAvailableHeight;
    }

    public boolean getHideHeaderRow() {
        return mHideHeaderRow;
    }

    public boolean getApplyCornerRadiusToLargeImages() {
        return mImageCornerRadius > 0;
    }

    public float getImageCornerRadius() {
        return mImageCornerRadius;
    }

    public int getRowHeight(RowContent row, SliceViewPolicy policy) {
        int maxHeight = policy.getMaxSmallHeight() > 0 ? policy.getMaxSmallHeight() : mRowMaxHeight;

        if (row.getRange() == null && row.getSelection() == null
                && policy.getMode() != MODE_LARGE) {
            return maxHeight;
        }

        if (row.getRange() != null) {
            // If no StartItem, keep to use original layout.
            if (row.getStartItem() == null) {
                // Range element always has set height and then the height of the text
                // area on the row will vary depending on 0,1 or 2 lines of text.
                int textAreaHeight =
                        row.getLineCount() == 0
                                ? 0
                                : (row.getLineCount() > 1
                                        ? mRowTextWithRangeHeight
                                        : mRowSingleTextWithRangeHeight);
                return textAreaHeight + mRowRangeHeight;
            } else {
                // If has StartItem then Range element is inline, the row height should be more to
                // fit thumb ripple.
                return mRowInlineRangeHeight;
            }
        }

        if (row.getSelection() != null) {
            // Selection element always has set height and then the height of the text
            // area on the row will vary depending on if 1 or 2 lines of text.
            int textAreaHeight = row.getLineCount() > 1 ? mRowTextWithSelectionHeight
                    : mRowSingleTextWithSelectionHeight;
            return textAreaHeight + mRowSelectionHeight;
        }

        return (row.getLineCount() > 1 || row.getIsHeader()) ? maxHeight : mRowMinHeight;
    }

    public int getGridHeight(GridContent grid, SliceViewPolicy policy) {
        boolean isSmall = policy.getMode() == MODE_SMALL;
        if (!grid.isValid()) {
            return 0;
        }
        int largestImageMode = grid.getLargestImageMode();
        int height;
        if (grid.isAllImages()) {
            height = (grid.getGridContent().size() == 1)
                    ? (isSmall
                    ? mGridBigPicMinHeight
                    : mGridBigPicMaxHeight)
                    : (largestImageMode == ICON_IMAGE
                            ? mGridMinHeight
                            : (largestImageMode == RAW_IMAGE_LARGE
                                    ? grid.getFirstImageSize(mContext).y
                                    : mGridAllImagesHeight));
        } else {
            boolean twoLines = grid.getMaxCellLineCount() > 1;
            boolean hasImage = grid.hasImage();
            boolean iconImagesOrNone = largestImageMode == ICON_IMAGE
                    || largestImageMode == UNKNOWN_IMAGE;
            height = largestImageMode == RAW_IMAGE_LARGE
                    ? (grid.getFirstImageSize(mContext).y
                        + (twoLines ? 2 : 1) * mGridRawImageTextHeight)
                    : (twoLines && !isSmall)
                            ? (hasImage
                            ? mGridMaxHeight
                            : mGridMinHeight)
                            : (iconImagesOrNone
                                    ? mGridMinHeight
                                    : mGridImageTextHeight);
        }
        int topPadding = grid.isAllImages() && grid.getRowIndex() == 0
                ? mGridTopPadding : 0;
        int bottomPadding = grid.isAllImages() && grid.getIsLastIndex()
                ? mGridBottomPadding : 0;
        return height + topPadding + bottomPadding;
    }

    public int getListHeight(ListContent list, SliceViewPolicy policy) {
        if (policy.getMode() == MODE_SMALL) {
            return list.getHeader().getHeight(this, policy);
        }
        int maxHeight = policy.getMaxHeight();
        boolean scrollable = policy.isScrollable();

        int desiredHeight = getListItemsHeight(list.getRowItems(), policy);
        if (maxHeight > 0) {
            // Always ensure we're at least the height of our small version.
            int smallHeight = list.getHeader().getHeight(this, policy);
            maxHeight = Math.max(smallHeight, maxHeight);
        }
        int maxLargeHeight = maxHeight > 0
                ? maxHeight
                : mListLargeHeight;
        // Do we have enough content to reasonably scroll in our max?
        boolean bigEnoughToScroll = desiredHeight - maxLargeHeight >= mListMinScrollHeight;

        // Adjust for scrolling
        int height = bigEnoughToScroll && !getExpandToAvailableHeight() ? maxLargeHeight
                : maxHeight <= 0 ? desiredHeight
                : Math.min(maxLargeHeight, desiredHeight);
        if (!scrollable) {
            height = getListItemsHeight(
                getListItemsForNonScrollingList(list, height, policy).getDisplayedItems(),
                policy);
        }
        return height;
    }

    public int getListItemsHeight(List<SliceContent> listItems, SliceViewPolicy policy) {
        if (listItems == null) {
            return 0;
        }

        int height = 0;
        for (int i = 0; i < listItems.size(); i++) {
            SliceContent listItem = listItems.get(i);
            if (i == 0 && shouldSkipFirstListItem(listItems)) {
                continue;
            }
            height += listItem.getHeight(this, policy);
        }
        return height;
    }

    /**
     * Returns a list of items that can fit in the provided height. If this list
     * has a see more item this will be displayed in the list if appropriate.
     *
     * @param list the list from which to source the items.
     * @param availableHeight to use to determine the row items to return.
     * @param policy the policy info (scrolling, mode) to use when determining row items to return.
     *
     * @return the list of items that can be displayed in the provided height.
     */
    @NonNull
    public DisplayedListItems getListItemsForNonScrollingList(ListContent list,
                                                             int availableHeight,
                                                             SliceViewPolicy policy) {
        ArrayList<SliceContent> visibleItems = new ArrayList<>();
        int hiddenItemCount = 0;
        if (list.getRowItems() == null || list.getRowItems().size() == 0) {
            return new DisplayedListItems(visibleItems, hiddenItemCount);
        }

        final boolean skipFirstItem = shouldSkipFirstListItem(list.getRowItems());

        int visibleHeight = 0;
        final int rowCount = list.getRowItems().size();
        for (int i = 0; i < rowCount; i++) {
            SliceContent listItem = list.getRowItems().get(i);
            if (i == 0 && skipFirstItem) {
                continue;
            }
            int itemHeight = listItem.getHeight(this, policy);
            if (availableHeight > 0 && visibleHeight + itemHeight > availableHeight) {
                hiddenItemCount = rowCount - i;
                break;
            } else {
                visibleHeight += itemHeight;
                visibleItems.add(listItem);
            }
        }


        // Only add see more if we're at least showing one item and it's not the header.
        final int minItemCountForSeeMore = skipFirstItem ? 1 : 2;
        if (list.getSeeMoreItem() != null && visibleItems.size() >= minItemCountForSeeMore
                && hiddenItemCount > 0) {
            // Need to show see more
            int seeMoreHeight = list.getSeeMoreItem().getHeight(this, policy);
            visibleHeight += seeMoreHeight;

            // Free enough vertical space to fit the see more item.
            while (visibleHeight > availableHeight
                    && visibleItems.size() >= minItemCountForSeeMore) {
                int lastIndex = visibleItems.size() - 1;
                SliceContent lastItem = visibleItems.get(lastIndex);
                visibleHeight -= lastItem.getHeight(this, policy);
                visibleItems.remove(lastIndex);
                hiddenItemCount++;
            }

            if (visibleItems.size() >= minItemCountForSeeMore) {
                visibleItems.add(list.getSeeMoreItem());
            } else {
                // Not possible to free enough vertical space. We'll show only the header.
                visibleHeight -= seeMoreHeight;
            }
        }
        if (visibleItems.size() == 0) {
            // Didn't have enough space to show anything; should still show something
            visibleItems.add(list.getRowItems().get(0));
        }
        return new DisplayedListItems(visibleItems, hiddenItemCount);
    }

    /**
     * Returns a list of items that should be displayed to the user.
     *
     * @param list the list from which to source the items.
     */
    @NonNull
    public List<SliceContent> getListItemsToDisplay(@NonNull ListContent list) {
        List<SliceContent> rowItems = list.getRowItems();
        if (rowItems.size() > 0 && shouldSkipFirstListItem(rowItems)) {
            return rowItems.subList(1, rowItems.size());
        }
        return rowItems;
    }

    /** Returns true if the first item of a list should be skipped. */
    private boolean shouldSkipFirstListItem(List<SliceContent> rowItems) {
        // Hide header row if requested, but only if there is at least one non-header row.
        return getHideHeaderRow() && rowItems.size() > 1 && rowItems.get(0) instanceof RowContent
                && ((RowContent) rowItems.get(0)).getIsHeader();
    }

}