blob: de55d5074341458e2d1d5636b9f6946fe8c180dd [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.ui.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.support.annotation.Px;
import android.support.annotation.StyleRes;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.ui.R;
/** The view responsible for displaying a material chip. */
public class ChipView extends LinearLayout {
/** An id to use for {@link #setIcon(int, boolean)} when there is no icon on the chip. */
public static final int INVALID_ICON_ID = -1;
private final RippleBackgroundHelper mRippleBackgroundHelper;
private final TextView mPrimaryText;
private final ChromeImageView mIcon;
private final @IdRes int mSecondaryTextAppearanceId;
private TextView mSecondaryText;
/**
* Constructor for inflating from XML.
*/
public ChipView(Context context, @StyleRes int chipStyle) {
this(context, null, chipStyle);
}
/**
* Constructor for inflating from XML.
*/
public ChipView(Context context, AttributeSet attrs) {
this(context, attrs, R.style.SuggestionChipThemeOverlay);
}
private ChipView(Context context, AttributeSet attrs, @StyleRes int themeOverlay) {
super(new ContextThemeWrapper(context, themeOverlay), attrs, R.attr.chipStyle);
final @Px int leadingElementPadding =
getResources().getDimensionPixelSize(R.dimen.chip_element_leading_padding);
final @Px int endPadding = getResources().getDimensionPixelSize(R.dimen.chip_end_padding);
TypedArray a = getContext().obtainStyledAttributes(
attrs, R.styleable.ChipView, R.attr.chipStyle, 0);
int chipColorId =
a.getResourceId(R.styleable.ChipView_chipColor, R.color.chip_background_color);
int rippleColorId =
a.getResourceId(R.styleable.ChipView_rippleColor, R.color.chip_ripple_color);
int cornerRadius = a.getDimensionPixelSize(R.styleable.ChipView_cornerRadius,
getContext().getResources().getDimensionPixelSize(R.dimen.chip_corner_radius));
int iconWidth = a.getDimensionPixelSize(R.styleable.ChipView_iconWidth,
getResources().getDimensionPixelSize(R.dimen.chip_icon_size));
int iconHeight = a.getDimensionPixelSize(R.styleable.ChipView_iconHeight,
getResources().getDimensionPixelSize(R.dimen.chip_icon_size));
int primaryTextAppearance = a.getResourceId(
R.styleable.ChipView_primaryTextAppearance, R.style.TextAppearance_ChipText);
mSecondaryTextAppearanceId = a.getResourceId(
R.styleable.ChipView_secondaryTextAppearance, R.style.TextAppearance_ChipText);
int verticalInset = a.getDimensionPixelSize(R.styleable.ChipView_verticalInset,
getResources().getDimensionPixelSize(R.dimen.chip_bg_vertical_inset));
a.recycle();
mIcon = new ChromeImageView(getContext());
mIcon.setLayoutParams(new LayoutParams(iconWidth, iconHeight));
addView(mIcon);
// Setting this enforces 16dp padding at the end and 8dp at the start. For text, the start
// padding needs to be 16dp which is why a ChipTextView contributes the remaining 8dp.
ViewCompat.setPaddingRelative(this, leadingElementPadding, 0, endPadding, 0);
mPrimaryText = new TextView(new ContextThemeWrapper(getContext(), R.style.ChipTextView));
ApiCompatibilityUtils.setTextAppearance(mPrimaryText, primaryTextAppearance);
addView(mPrimaryText);
// Reset icon and background:
mRippleBackgroundHelper = new RippleBackgroundHelper(this, chipColorId, rippleColorId,
cornerRadius, R.color.chip_stroke_color, R.dimen.chip_border_width, verticalInset);
setIcon(INVALID_ICON_ID, false);
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mRippleBackgroundHelper != null) {
mRippleBackgroundHelper.onDrawableStateChanged();
}
}
/**
* Sets the icon at the start of the chip view.
* @param icon The resource id pointing to the icon.
*/
public void setIcon(@DrawableRes int icon, boolean tintWithTextColor) {
if (icon == INVALID_ICON_ID) {
mIcon.setVisibility(ViewGroup.GONE);
return;
}
mIcon.setVisibility(ViewGroup.VISIBLE);
mIcon.setImageResource(icon);
setTint(tintWithTextColor);
}
/**
* Sets the icon at the start of the chip view.
* @param drawable Drawable to display.
*/
public void setIcon(Drawable drawable, boolean tintWithTextColor) {
mIcon.setVisibility(ViewGroup.VISIBLE);
mIcon.setImageDrawable(drawable);
setTint(tintWithTextColor);
}
/**
* Returns the {@link TextView} that contains the label of the chip.
* @return A {@link TextView}.
*/
public TextView getPrimaryTextView() {
return mPrimaryText;
}
/**
* Returns the {@link TextView} that contains the secondary label of the chip. If it wasn't used
* until now, this creates the view.
* @return A {@link TextView}.
*/
public TextView getSecondaryTextView() {
if (mSecondaryText == null) {
mSecondaryText =
new TextView(new ContextThemeWrapper(getContext(), R.style.ChipTextView));
ApiCompatibilityUtils.setTextAppearance(mSecondaryText, mSecondaryTextAppearanceId);
addView(mSecondaryText);
}
return mSecondaryText;
}
/**
* Sets the correct tinting on the Chip's image view.
* @param tintWithTextColor If true then the image view will be tinted with the primary text
* color. If not, the tint will be cleared.
*/
private void setTint(boolean tintWithTextColor) {
if (mPrimaryText.getTextColors() != null && tintWithTextColor) {
ApiCompatibilityUtils.setImageTintList(mIcon, mPrimaryText.getTextColors());
} else {
ApiCompatibilityUtils.setImageTintList(mIcon, null);
}
}
}