ErrorSupportFragment.java revision 61905b0b52c50018dcaebcd79699c39b8f28d622
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 android.support.v17.leanback.app;
15
16import android.os.Bundle;
17import android.support.v17.leanback.R;
18import android.support.v17.leanback.widget.TitleView;
19import android.text.TextUtils;
20import android.util.Log;
21import android.support.v4.app.Fragment;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.View.OnClickListener;
25import android.view.ViewGroup;
26import android.widget.Button;
27import android.widget.ImageView;
28import android.widget.TextView;
29import android.graphics.Paint;
30import android.graphics.PixelFormat;
31import android.graphics.Paint.FontMetricsInt;
32import android.graphics.drawable.Drawable;
33
34/**
35 * A fragment for displaying an error indication.
36 */
37public class ErrorSupportFragment extends Fragment {
38
39    private View mErrorFrame;
40    private String mTitle;
41    private Drawable mBadgeDrawable;
42    private TitleView mTitleView;
43    private ImageView mImageView;
44    private TextView mTextView;
45    private Button mButton;
46    private Drawable mDrawable;
47    private CharSequence mMessage;
48    private String mButtonText;
49    private View.OnClickListener mButtonClickListener;
50    private Drawable mBackgroundDrawable;
51    private boolean mIsBackgroundTranslucent = true;
52
53    /**
54     * Sets the drawable displayed in the browse fragment title.
55     *
56     * @param drawable The drawable to display in the browse fragment title.
57     */
58    public void setBadgeDrawable(Drawable drawable) {
59        mBadgeDrawable = drawable;
60        updateTitle();
61    }
62
63    /**
64     * Returns the badge drawable used in the fragment title.
65     */
66    public Drawable getBadgeDrawable() {
67        return mBadgeDrawable;
68    }
69
70    /**
71     * Sets a title for the browse fragment.
72     *
73     * @param title The title of the browse fragment.
74     */
75    public void setTitle(String title) {
76        mTitle = title;
77        updateTitle();
78    }
79
80    /**
81     * Returns the title for the browse fragment.
82     */
83    public String getTitle() {
84        return mTitle;
85    }
86
87    /**
88     * Sets the default background.
89     *
90     * @param translucent True to set a translucent background.
91     */
92    public void setDefaultBackground(boolean translucent) {
93        mBackgroundDrawable = null;
94        mIsBackgroundTranslucent = translucent;
95        updateBackground();
96        updateMessage();
97    }
98
99    /**
100     * Returns true if the background is translucent.
101     */
102    public boolean isBackgroundTranslucent() {
103        return mIsBackgroundTranslucent;
104    }
105
106    /**
107     * Sets a drawable for the fragment background.
108     *
109     * @param drawable The drawable used for the background.
110     */
111    public void setBackgroundDrawable(Drawable drawable) {
112        mBackgroundDrawable = drawable;
113        if (drawable != null) {
114            final int opacity = drawable.getOpacity();
115            mIsBackgroundTranslucent = (opacity == PixelFormat.TRANSLUCENT ||
116                    opacity == PixelFormat.TRANSPARENT);
117        }
118        updateBackground();
119        updateMessage();
120    }
121
122    /**
123     * Returns the background drawable.  May be null if a default is used.
124     */
125    public Drawable getBackgroundDrawable() {
126        return mBackgroundDrawable;
127    }
128
129    /**
130     * Sets the drawable to be used for the error image.
131     *
132     * @param drawable The drawable used for the error image.
133     */
134    public void setImageDrawable(Drawable drawable) {
135        mDrawable = drawable;
136        updateImageDrawable();
137    }
138
139    /**
140     * Returns the drawable used for the error image.
141     */
142    public Drawable getImageDrawable() {
143        return mDrawable;
144    }
145
146    /**
147     * Sets the error message.
148     *
149     * @param message The error message.
150     */
151    public void setMessage(CharSequence message) {
152        mMessage = message;
153        updateMessage();
154    }
155
156    /**
157     * Returns the error message.
158     */
159    public CharSequence getMessage() {
160        return mMessage;
161    }
162
163    /**
164     * Sets the button text.
165     *
166     * @param text The button text.
167     */
168    public void setButtonText(String text) {
169        mButtonText = text;
170        updateButton();
171    }
172
173    /**
174     * Returns the button text.
175     */
176    public String getButtonText() {
177        return mButtonText;
178    }
179
180    /**
181     * Set the button click listener.
182     *
183     * @param clickListener The click listener for the button.
184     */
185    public void setButtonClickListener(View.OnClickListener clickListener) {
186        mButtonClickListener = clickListener;
187        updateButton();
188    }
189
190    /**
191     * Returns the button click listener.
192     */
193    public View.OnClickListener getButtonClickListener() {
194        return mButtonClickListener;
195    }
196
197    @Override
198    public View onCreateView(LayoutInflater inflater, ViewGroup container,
199            Bundle savedInstanceState) {
200        View root = inflater.inflate(R.layout.lb_error_fragment, container, false);
201
202        mErrorFrame = root.findViewById(R.id.error_frame);
203        updateBackground();
204
205        mImageView = (ImageView) root.findViewById(R.id.image);
206        updateImageDrawable();
207
208        mTextView = (TextView) root.findViewById(R.id.message);
209        updateMessage();
210
211        mButton = (Button) root.findViewById(R.id.button);
212        updateButton();
213
214        mTitleView = (TitleView) root.findViewById(R.id.browse_title_group);
215        updateTitle();
216
217        FontMetricsInt metrics = getFontMetricsInt(mTextView);
218        int underImageBaselineMargin = container.getResources().getDimensionPixelSize(
219                R.dimen.lb_error_under_image_baseline_margin);
220        setTopMargin(mTextView, underImageBaselineMargin + metrics.ascent);
221
222        int underMessageBaselineMargin = container.getResources().getDimensionPixelSize(
223                R.dimen.lb_error_under_message_baseline_margin);
224        setTopMargin(mButton, underMessageBaselineMargin - metrics.descent);
225
226        return root;
227    }
228
229    private void updateBackground() {
230        if (mErrorFrame != null) {
231            if (mBackgroundDrawable != null) {
232                mErrorFrame.setBackground(mBackgroundDrawable);
233            } else {
234                mErrorFrame.setBackgroundColor(mErrorFrame.getResources().getColor(
235                        mIsBackgroundTranslucent ?
236                        R.color.lb_error_background_color_translucent :
237                        R.color.lb_error_background_color_opaque));
238            }
239        }
240    }
241
242    private void updateTitle() {
243        if (mTitleView != null) {
244            mTitleView.setTitle(mTitle);
245            mTitleView.setBadgeDrawable(mBadgeDrawable);
246        }
247    }
248
249    private void updateMessage() {
250        if (mTextView != null) {
251            mTextView.setText(mMessage);
252            mTextView.setTextColor(mTextView.getResources().getColor(mIsBackgroundTranslucent ?
253                    R.color.lb_error_message_color_on_translucent :
254                    R.color.lb_error_message_color_on_opaque));
255            mTextView.setVisibility(TextUtils.isEmpty(mMessage) ? View.GONE : View.VISIBLE);
256        }
257    }
258
259    private void updateImageDrawable() {
260        if (mImageView != null) {
261            mImageView.setImageDrawable(mDrawable);
262            mImageView.setVisibility(mDrawable == null ? View.GONE : View.VISIBLE);
263        }
264    }
265
266    private void updateButton() {
267        if (mButton != null) {
268            mButton.setText(mButtonText);
269            mButton.setOnClickListener(mButtonClickListener);
270            mButton.setVisibility(TextUtils.isEmpty(mButtonText) ? View.GONE : View.VISIBLE);
271            mButton.requestFocus();
272        }
273    }
274
275    @Override
276    public void onStart() {
277        super.onStart();
278        mErrorFrame.requestFocus();
279    }
280
281    private static FontMetricsInt getFontMetricsInt(TextView textView) {
282        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
283        paint.setTextSize(textView.getTextSize());
284        paint.setTypeface(textView.getTypeface());
285        return paint.getFontMetricsInt();
286    }
287
288    private static void setTopMargin(TextView textView, int topMargin) {
289        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) textView.getLayoutParams();
290        lp.topMargin = topMargin;
291        textView.setLayoutParams(lp);
292    }
293}
294