mirror of
https://github.com/material-components/material-components-android.git
synced 2026-01-20 20:12:52 +08:00
Bazel is happier if Java/Java test roots are named 'java' and 'javatests', and
this will mean that once we create a BUILD file for
android/support/design/{widget,internal}/ we'll no longer need a custom package
specified in our build (which tends to cause build problems that manifest quite
weirdly). This commit doesn't attempt to refactor the build at all yet, and is
just a pure move.
PiperOrigin-RevId: 178060739
176 lines
7.5 KiB
Java
176 lines
7.5 KiB
Java
/*
|
|
* Copyright (C) 2017 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 android.support.design.button;
|
|
|
|
import android.animation.AnimatorInflater;
|
|
import android.content.Context;
|
|
import android.content.res.ColorStateList;
|
|
import android.content.res.TypedArray;
|
|
import android.graphics.PorterDuff.Mode;
|
|
import android.graphics.drawable.Drawable;
|
|
import android.os.Build.VERSION;
|
|
import android.os.Build.VERSION_CODES;
|
|
import android.support.annotation.StyleRes;
|
|
import android.support.design.resources.MaterialResources;
|
|
import android.support.design.theme.ThemeUtils;
|
|
import android.support.design.widget.ViewUtils;
|
|
import android.support.v4.graphics.drawable.DrawableCompat;
|
|
import android.support.v4.widget.TextViewCompat;
|
|
import android.support.v7.widget.AppCompatButton;
|
|
import android.util.AttributeSet;
|
|
import android.view.Gravity;
|
|
|
|
/**
|
|
* A convenience class for creating a new Material button.
|
|
*
|
|
* <p>This class supplies updated Material styles for the button in the constructor. The widget will
|
|
* display the correct default Material styles without the use of the style flag.
|
|
*
|
|
* <p>For filled Material buttons, this class uses your theme's {@code ?attr/colorAccent} for the
|
|
* background fill color and white for the text color. For unfilled buttons, this class uses {@code
|
|
* ?attr/colorAccent} for the text color and transparent for the background.
|
|
*
|
|
* <p>Add icons to the start of this Material Button using the {@code icon}, {@code iconPadding},
|
|
* {@code iconTint} and {@code iconTintMode} attributes.
|
|
*
|
|
* <p>Specify background tint using the {@code buttonBackgroundTint} attribute, which accepts either
|
|
* a color or a color state list.
|
|
*
|
|
* <p>Ripple color / press state color can be specified using the {@code rippleColor} attribute.
|
|
* Ripple opacity will be determined by the Android framework when available. Otherwise, this color
|
|
* will be overlaid on the button at a 50% opacity when button is pressed.
|
|
*
|
|
* <p>Set the stroke color using the {@code strokeColor} attribute, which accepts either a color or
|
|
* a color state list. Stroke width can be set using the {@code strokeWidth} attribute.
|
|
*
|
|
* <p>Specify the radius of all four corners of the button using the {@code cornerRadius} attribute.
|
|
*/
|
|
public class MaterialButton extends AppCompatButton {
|
|
|
|
public MaterialButton(Context context) {
|
|
this(context, null /* attrs */);
|
|
}
|
|
|
|
public MaterialButton(Context context, AttributeSet attrs) {
|
|
this(context, attrs, R.attr.materialButtonStyle);
|
|
}
|
|
|
|
public MaterialButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
super(context, attrs, defStyleAttr);
|
|
|
|
ThemeUtils.checkAppCompatTheme(context);
|
|
|
|
TypedArray attributes =
|
|
context.obtainStyledAttributes(
|
|
attrs,
|
|
R.styleable.MaterialButton,
|
|
defStyleAttr,
|
|
R.style.Widget_Design_Button_MaterialButton);
|
|
int minWidth = attributes.getDimensionPixelSize(R.styleable.MaterialButton_android_minWidth, 0);
|
|
int minHeight =
|
|
attributes.getDimensionPixelSize(R.styleable.MaterialButton_android_minHeight, 0);
|
|
|
|
int padding = attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_padding, 0);
|
|
int paddingLeft =
|
|
attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_paddingLeft, padding);
|
|
int paddingRight =
|
|
attributes.getDimensionPixelOffset(
|
|
R.styleable.MaterialButton_android_paddingRight, padding);
|
|
int paddingTop =
|
|
attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_paddingTop, padding);
|
|
int paddingBottom =
|
|
attributes.getDimensionPixelOffset(
|
|
R.styleable.MaterialButton_android_paddingBottom, padding);
|
|
|
|
int insetLeft =
|
|
attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_insetLeft, 0);
|
|
int insetRight =
|
|
attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_insetRight, 0);
|
|
int insetTop =
|
|
attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_insetTop, 0);
|
|
int insetBottom =
|
|
attributes.getDimensionPixelOffset(R.styleable.MaterialButton_android_insetBottom, 0);
|
|
|
|
int additionalPaddingLeftForIcon =
|
|
attributes.getDimensionPixelOffset(
|
|
R.styleable.MaterialButton_additionalPaddingLeftForIcon, 0);
|
|
int additionalPaddingRightForIcon =
|
|
attributes.getDimensionPixelOffset(
|
|
R.styleable.MaterialButton_additionalPaddingRightForIcon, 0);
|
|
|
|
@StyleRes
|
|
int textAppearanceStyleRes =
|
|
attributes.getResourceId(R.styleable.MaterialButton_android_textAppearance, 0);
|
|
int animatorResId =
|
|
attributes.getResourceId(R.styleable.MaterialButton_android_stateListAnimator, 0);
|
|
boolean isFocusable = attributes.getBoolean(R.styleable.MaterialButton_android_focusable, true);
|
|
boolean isClickable = attributes.getBoolean(R.styleable.MaterialButton_android_clickable, true);
|
|
int iconPadding = attributes.getDimensionPixelSize(R.styleable.MaterialButton_iconPadding, 0);
|
|
int gravity = attributes.getInt(R.styleable.MaterialButton_android_gravity, Gravity.CENTER);
|
|
Mode iconTintMode =
|
|
ViewUtils.parseTintMode(
|
|
attributes.getInt(R.styleable.MaterialButton_iconTintMode, -1), null);
|
|
|
|
// Workaround to support VectorDrawables on pre-Lollipop, as there is no compat implementation
|
|
// for icon within AppCompatButton
|
|
ColorStateList iconTint =
|
|
MaterialResources.getColorStateList(
|
|
getContext(), attributes, R.styleable.MaterialButton_iconTint);
|
|
Drawable icon =
|
|
MaterialResources.getDrawable(getContext(), attributes, R.styleable.MaterialButton_icon);
|
|
|
|
// Loads and sets background drawable attributes
|
|
MaterialButtonHelper buttonHelper = new MaterialButtonHelper(this);
|
|
buttonHelper.loadFromAttributes(attributes);
|
|
|
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && animatorResId != 0) {
|
|
setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, animatorResId));
|
|
}
|
|
|
|
TextViewCompat.setTextAppearance(this, textAppearanceStyleRes);
|
|
setMinWidth(minWidth);
|
|
setMinHeight(minHeight);
|
|
setFocusable(isFocusable);
|
|
setClickable(isClickable);
|
|
setCompoundDrawablePadding(iconPadding);
|
|
setGravity(gravity);
|
|
|
|
// TODO: Add attribute for pressed state color
|
|
// TODO: Add attributes for elevation/translationZ
|
|
|
|
// setPadding() sets padding on button including inset, so we have to add inset and padding
|
|
// attributes to get the button's visible padding to look correct
|
|
setPaddingRelative(
|
|
paddingLeft + (icon != null ? additionalPaddingLeftForIcon : 0) + insetLeft,
|
|
paddingTop + insetTop,
|
|
paddingRight + (icon != null ? additionalPaddingRightForIcon : 0) + insetRight,
|
|
paddingBottom + insetBottom);
|
|
|
|
if (icon != null) {
|
|
icon = icon.mutate();
|
|
DrawableCompat.setTintList(icon, iconTint);
|
|
if (iconTintMode != null) {
|
|
DrawableCompat.setTintMode(icon, iconTintMode);
|
|
}
|
|
}
|
|
|
|
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(this, icon, null, null, null);
|
|
|
|
attributes.recycle();
|
|
}
|
|
}
|