ErrorSupportFragment.java revision b31c3281d870e9abb673db239234d580dcc4feff
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package androidx.leanback.app;
15
16import android.graphics.Paint;
17import android.graphics.Paint.FontMetricsInt;
18import android.graphics.PixelFormat;
19import android.graphics.drawable.Drawable;
20import android.os.Bundle;
21import androidx.leanback.R;
22import android.text.TextUtils;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.Button;
27import android.widget.ImageView;
28import android.widget.TextView;
29
30/**
31 * A fragment for displaying an error indication.
32 */
33public class ErrorSupportFragment extends BrandedSupportFragment {
34
35    private ViewGroup mErrorFrame;
36    private ImageView mImageView;
37    private TextView mTextView;
38    private Button mButton;
39    private Drawable mDrawable;
40    private CharSequence mMessage;
41    private String mButtonText;
42    private View.OnClickListener mButtonClickListener;
43    private Drawable mBackgroundDrawable;
44    private boolean mIsBackgroundTranslucent = true;
45
46    /**
47     * Sets the default background.
48     *
49     * @param translucent True to set a translucent background.
50     */
51    public void setDefaultBackground(boolean translucent) {
52        mBackgroundDrawable = null;
53        mIsBackgroundTranslucent = translucent;
54        updateBackground();
55        updateMessage();
56    }
57
58    /**
59     * Returns true if the background is translucent.
60     */
61    public boolean isBackgroundTranslucent() {
62        return mIsBackgroundTranslucent;
63    }
64
65    /**
66     * Sets a drawable for the fragment background.
67     *
68     * @param drawable The drawable used for the background.
69     */
70    public void setBackgroundDrawable(Drawable drawable) {
71        mBackgroundDrawable = drawable;
72        if (drawable != null) {
73            final int opacity = drawable.getOpacity();
74            mIsBackgroundTranslucent = (opacity == PixelFormat.TRANSLUCENT
75                    || opacity == PixelFormat.TRANSPARENT);
76        }
77        updateBackground();
78        updateMessage();
79    }
80
81    /**
82     * Returns the background drawable.  May be null if a default is used.
83     */
84    public Drawable getBackgroundDrawable() {
85        return mBackgroundDrawable;
86    }
87
88    /**
89     * Sets the drawable to be used for the error image.
90     *
91     * @param drawable The drawable used for the error image.
92     */
93    public void setImageDrawable(Drawable drawable) {
94        mDrawable = drawable;
95        updateImageDrawable();
96    }
97
98    /**
99     * Returns the drawable used for the error image.
100     */
101    public Drawable getImageDrawable() {
102        return mDrawable;
103    }
104
105    /**
106     * Sets the error message.
107     *
108     * @param message The error message.
109     */
110    public void setMessage(CharSequence message) {
111        mMessage = message;
112        updateMessage();
113    }
114
115    /**
116     * Returns the error message.
117     */
118    public CharSequence getMessage() {
119        return mMessage;
120    }
121
122    /**
123     * Sets the button text.
124     *
125     * @param text The button text.
126     */
127    public void setButtonText(String text) {
128        mButtonText = text;
129        updateButton();
130    }
131
132    /**
133     * Returns the button text.
134     */
135    public String getButtonText() {
136        return mButtonText;
137    }
138
139    /**
140     * Set the button click listener.
141     *
142     * @param clickListener The click listener for the button.
143     */
144    public void setButtonClickListener(View.OnClickListener clickListener) {
145        mButtonClickListener = clickListener;
146        updateButton();
147    }
148
149    /**
150     * Returns the button click listener.
151     */
152    public View.OnClickListener getButtonClickListener() {
153        return mButtonClickListener;
154    }
155
156    @Override
157    public View onCreateView(LayoutInflater inflater, ViewGroup container,
158            Bundle savedInstanceState) {
159        View root = inflater.inflate(R.layout.lb_error_fragment, container, false);
160
161        mErrorFrame = (ViewGroup) root.findViewById(R.id.error_frame);
162        updateBackground();
163
164        installTitleView(inflater, mErrorFrame, savedInstanceState);
165
166        mImageView = (ImageView) root.findViewById(R.id.image);
167        updateImageDrawable();
168
169        mTextView = (TextView) root.findViewById(R.id.message);
170        updateMessage();
171
172        mButton = (Button) root.findViewById(R.id.button);
173        updateButton();
174
175        FontMetricsInt metrics = getFontMetricsInt(mTextView);
176        int underImageBaselineMargin = container.getResources().getDimensionPixelSize(
177                R.dimen.lb_error_under_image_baseline_margin);
178        setTopMargin(mTextView, underImageBaselineMargin + metrics.ascent);
179
180        int underMessageBaselineMargin = container.getResources().getDimensionPixelSize(
181                R.dimen.lb_error_under_message_baseline_margin);
182        setTopMargin(mButton, underMessageBaselineMargin - metrics.descent);
183
184        return root;
185    }
186
187    private void updateBackground() {
188        if (mErrorFrame != null) {
189            if (mBackgroundDrawable != null) {
190                mErrorFrame.setBackground(mBackgroundDrawable);
191            } else {
192                mErrorFrame.setBackgroundColor(mErrorFrame.getResources().getColor(
193                        mIsBackgroundTranslucent
194                                ? R.color.lb_error_background_color_translucent
195                                : R.color.lb_error_background_color_opaque));
196            }
197        }
198    }
199
200    private void updateMessage() {
201        if (mTextView != null) {
202            mTextView.setText(mMessage);
203            mTextView.setVisibility(TextUtils.isEmpty(mMessage) ? View.GONE : View.VISIBLE);
204        }
205    }
206
207    private void updateImageDrawable() {
208        if (mImageView != null) {
209            mImageView.setImageDrawable(mDrawable);
210            mImageView.setVisibility(mDrawable == null ? View.GONE : View.VISIBLE);
211        }
212    }
213
214    private void updateButton() {
215        if (mButton != null) {
216            mButton.setText(mButtonText);
217            mButton.setOnClickListener(mButtonClickListener);
218            mButton.setVisibility(TextUtils.isEmpty(mButtonText) ? View.GONE : View.VISIBLE);
219            mButton.requestFocus();
220        }
221    }
222
223    @Override
224    public void onStart() {
225        super.onStart();
226        mErrorFrame.requestFocus();
227    }
228
229    private static FontMetricsInt getFontMetricsInt(TextView textView) {
230        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
231        paint.setTextSize(textView.getTextSize());
232        paint.setTypeface(textView.getTypeface());
233        return paint.getFontMetricsInt();
234    }
235
236    private static void setTopMargin(TextView textView, int topMargin) {
237        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) textView.getLayoutParams();
238        lp.topMargin = topMargin;
239        textView.setLayoutParams(lp);
240    }
241
242}
243