SnackbarContentLayout.java revision 8e10080c914d1ad0784394fa3026b85535535847
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.support.design.internal;
17
18import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
19
20import android.content.Context;
21import android.content.res.TypedArray;
22import android.support.annotation.RestrictTo;
23import android.support.design.R;
24import android.support.design.widget.BaseTransientBottomBar;
25import android.support.v4.view.ViewCompat;
26import android.util.AttributeSet;
27import android.view.View;
28import android.widget.Button;
29import android.widget.LinearLayout;
30import android.widget.TextView;
31
32/**
33 * @hide
34 */
35@RestrictTo(LIBRARY_GROUP)
36public class SnackbarContentLayout extends LinearLayout implements
37        BaseTransientBottomBar.ContentViewCallback {
38    private TextView mMessageView;
39    private Button mActionView;
40
41    private int mMaxWidth;
42    private int mMaxInlineActionWidth;
43
44    public SnackbarContentLayout(Context context) {
45        this(context, null);
46    }
47
48    public SnackbarContentLayout(Context context, AttributeSet attrs) {
49        super(context, attrs);
50        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SnackbarLayout);
51        mMaxWidth = a.getDimensionPixelSize(R.styleable.SnackbarLayout_android_maxWidth, -1);
52        mMaxInlineActionWidth = a.getDimensionPixelSize(
53                R.styleable.SnackbarLayout_maxActionInlineWidth, -1);
54        a.recycle();
55    }
56
57    @Override
58    protected void onFinishInflate() {
59        super.onFinishInflate();
60        mMessageView = (TextView) findViewById(R.id.snackbar_text);
61        mActionView = (Button) findViewById(R.id.snackbar_action);
62    }
63
64    public TextView getMessageView() {
65        return mMessageView;
66    }
67
68    public Button getActionView() {
69        return mActionView;
70    }
71
72    @Override
73    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
74        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
75
76        if (mMaxWidth > 0 && getMeasuredWidth() > mMaxWidth) {
77            widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, MeasureSpec.EXACTLY);
78            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
79        }
80
81        final int multiLineVPadding = getResources().getDimensionPixelSize(
82                R.dimen.design_snackbar_padding_vertical_2lines);
83        final int singleLineVPadding = getResources().getDimensionPixelSize(
84                R.dimen.design_snackbar_padding_vertical);
85        final boolean isMultiLine = mMessageView.getLayout().getLineCount() > 1;
86
87        boolean remeasure = false;
88        if (isMultiLine && mMaxInlineActionWidth > 0
89                && mActionView.getMeasuredWidth() > mMaxInlineActionWidth) {
90            if (updateViewsWithinLayout(VERTICAL, multiLineVPadding,
91                    multiLineVPadding - singleLineVPadding)) {
92                remeasure = true;
93            }
94        } else {
95            final int messagePadding = isMultiLine ? multiLineVPadding : singleLineVPadding;
96            if (updateViewsWithinLayout(HORIZONTAL, messagePadding, messagePadding)) {
97                remeasure = true;
98            }
99        }
100
101        if (remeasure) {
102            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
103        }
104    }
105
106    private boolean updateViewsWithinLayout(final int orientation,
107            final int messagePadTop, final int messagePadBottom) {
108        boolean changed = false;
109        if (orientation != getOrientation()) {
110            setOrientation(orientation);
111            changed = true;
112        }
113        if (mMessageView.getPaddingTop() != messagePadTop
114                || mMessageView.getPaddingBottom() != messagePadBottom) {
115            updateTopBottomPadding(mMessageView, messagePadTop, messagePadBottom);
116            changed = true;
117        }
118        return changed;
119    }
120
121    private static void updateTopBottomPadding(View view, int topPadding, int bottomPadding) {
122        if (ViewCompat.isPaddingRelative(view)) {
123            ViewCompat.setPaddingRelative(view,
124                    ViewCompat.getPaddingStart(view), topPadding,
125                    ViewCompat.getPaddingEnd(view), bottomPadding);
126        } else {
127            view.setPadding(view.getPaddingLeft(), topPadding,
128                    view.getPaddingRight(), bottomPadding);
129        }
130    }
131
132    @Override
133    public void animateContentIn(int delay, int duration) {
134        ViewCompat.setAlpha(mMessageView, 0f);
135        ViewCompat.animate(mMessageView).alpha(1f).setDuration(duration)
136                .setStartDelay(delay).start();
137
138        if (mActionView.getVisibility() == VISIBLE) {
139            ViewCompat.setAlpha(mActionView, 0f);
140            ViewCompat.animate(mActionView).alpha(1f).setDuration(duration)
141                    .setStartDelay(delay).start();
142        }
143    }
144
145    @Override
146    public void animateContentOut(int delay, int duration) {
147        ViewCompat.setAlpha(mMessageView, 1f);
148        ViewCompat.animate(mMessageView).alpha(0f).setDuration(duration)
149                .setStartDelay(delay).start();
150
151        if (mActionView.getVisibility() == VISIBLE) {
152            ViewCompat.setAlpha(mActionView, 1f);
153            ViewCompat.animate(mActionView).alpha(0f).setDuration(duration)
154                    .setStartDelay(delay).start();
155        }
156    }
157}
158