diff options
Diffstat (limited to 'src/com/android/deskclock/widget/MotionButton.java')
-rw-r--r-- | src/com/android/deskclock/widget/MotionButton.java | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/com/android/deskclock/widget/MotionButton.java b/src/com/android/deskclock/widget/MotionButton.java new file mode 100644 index 000000000..341b45e11 --- /dev/null +++ b/src/com/android/deskclock/widget/MotionButton.java @@ -0,0 +1,185 @@ +package com.android.deskclock.widget; + +/* + * Copyright (C) 2020 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. + */ + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Outline; +import android.graphics.Path; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewOutlineProvider; + +import androidx.appcompat.widget.AppCompatButton; + +import com.android.deskclock.R; + +/** + * A MotionButton is an AppCompatButton that can round its edges. <b>Added in 2.0</b> + * <p> + * Subclass of AppCompatButton to handle rounding edges dynamically. + * </p> + * <h2>MotionButton attributes</h2> + * <td>round</td> + * <td>(id) call the TransitionListener with this trigger id</td> + * </tr> + * <tr> + * <td>roundPercent</td> + * <td>Set the corner radius of curvature as a fraction of the smaller side. + * For squares 1 will result in a circle</td> + * </tr> + * <tr> + * <td>round</td> + * <td>Set the corner radius of curvature as a fraction of the smaller side. + * For squares 1 will result in a circle</td> + * </tr> + * + * </table> + */ +public class MotionButton extends AppCompatButton { + private float mRoundPercent = 0; // rounds the corners as a percent + private float mRound = Float.NaN; // rounds the corners in dp if NaN RoundPercent is in effect + private Path mPath; + ViewOutlineProvider mViewOutlineProvider; + RectF mRect; + + public MotionButton(Context context) { + super(context); + init(context, null); + } + + public MotionButton(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public MotionButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + setPadding(0, 0, 0, 0); + if (attrs != null) { + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MotionButton); + final int N = a.getIndexCount(); + for (int i = 0; i < N; i++) { + int attr = a.getIndex(i); + if (attr == R.styleable.MotionButton_round) { + setRound(a.getDimension(attr, 0)); + } else if (attr == R.styleable.MotionButton_roundPercent) { + setRoundPercent(a.getFloat(attr, 0)); + } + } + a.recycle(); + } + } + + /** + * Set the corner radius of curvature as a fraction of the smaller side. + * For squares 1 will result in a circle + * + * @param round the radius of curvature as a fraction of the smaller width + */ + public void setRoundPercent(float round) { + boolean change = (mRoundPercent != round); + mRoundPercent = round; + if (mRoundPercent != 0.0f) { + if (mPath == null) { + mPath = new Path(); + } + if (mRect == null) { + mRect = new RectF(); + } + if (mViewOutlineProvider == null) { + mViewOutlineProvider = new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + int w = getWidth(); + int h = getHeight(); + float r = Math.min(w, h) * mRoundPercent / 2; + outline.setRoundRect(0, 0, w, h, r); + } + }; + setOutlineProvider(mViewOutlineProvider); + } + setClipToOutline(true); + int w = getWidth(); + int h = getHeight(); + float r = Math.min(w, h) * mRoundPercent / 2; + mRect.set(0, 0, w, h); + mPath.reset(); + mPath.addRoundRect(mRect, r, r, Path.Direction.CW); + } else { + setClipToOutline(false); + } + if (change) { + invalidateOutline(); + } + } + + /** + * Set the corner radius of curvature + * + * @param round the radius of curvature NaN = default meaning roundPercent in effect + */ + public void setRound(float round) { + if (Float.isNaN(round)) { + mRound = round; + float tmp = mRoundPercent; + mRoundPercent = -1; + setRoundPercent(tmp); // force eval of roundPercent + return; + } + boolean change = (mRound != round); + mRound = round; + + if (mRound != 0.0f) { + if (mPath == null) { + mPath = new Path(); + } + if (mRect == null) { + mRect = new RectF(); + } + if (mViewOutlineProvider == null) { + mViewOutlineProvider = new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + int w = getWidth(); + int h = getHeight(); + outline.setRoundRect(0, 0, w, h, mRound); + } + }; + setOutlineProvider(mViewOutlineProvider); + } + setClipToOutline(true); + + int w = getWidth(); + int h = getHeight(); + mRect.set(0, 0, w, h); + mPath.reset(); + mPath.addRoundRect(mRect, mRound, mRound, Path.Direction.CW); + } else { + setClipToOutline(false); + } + if (change) { + invalidateOutline(); + } + + } +} |