1 /* 2 * Copyright (C) 2014 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 */ 16 17 package com.android.tv.settings.dialog.old; 18 19 import android.animation.ObjectAnimator; 20 import android.app.Activity; 21 import android.content.Context; 22 import android.graphics.Bitmap; 23 import android.graphics.Color; 24 import android.graphics.drawable.Drawable; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.view.accessibility.AccessibilityManager; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.view.ViewGroup.LayoutParams; 32 import android.widget.ImageView; 33 import android.widget.RelativeLayout; 34 import android.widget.TextView; 35 36 import com.android.tv.settings.R; 37 import com.android.tv.settings.widget.BitmapDownloader; 38 import com.android.tv.settings.widget.BitmapDownloader.BitmapCallback; 39 import com.android.tv.settings.widget.BitmapWorkerOptions; 40 import com.android.tv.settings.widget.FrameLayoutWithShadows; 41 42 /** 43 * This class exists to make extending both v4 fragments and regular fragments easy 44 */ 45 public class BaseContentFragment { 46 47 private static final String EXTRA_TITLE = "title"; 48 private static final String EXTRA_BREADCRUMB = "breadcrumb"; 49 private static final String EXTRA_DESCRIPTION = "description"; 50 private static final String EXTRA_ICON_RESOURCE_ID = "iconResourceId"; 51 private static final String EXTRA_ICON_URI = "iconUri"; 52 private static final String EXTRA_ICON_BITMAP = "iconBitmap"; 53 private static final String EXTRA_ICON_BACKGROUND = "iconBackground"; 54 55 public static Bundle buildArgs(String title) { 56 return buildArgs(title, null, null, 0, null, null, Color.TRANSPARENT); 57 } 58 59 public static Bundle buildArgs(String title, String breadcrumb, String description) { 60 return buildArgs(title, breadcrumb, description, 0, null, null, Color.TRANSPARENT); 61 } 62 63 public static Bundle buildArgs( 64 String title, String breadcrumb, String description, int iconResourceId, 65 int backgroundColor) { 66 return buildArgs(title, breadcrumb, description, iconResourceId, null, null, 67 backgroundColor); 68 } 69 70 public static Bundle buildArgs(String title, String breadcrumb, String description, Uri iconUri, 71 int backgroundColor) { 72 return buildArgs(title, breadcrumb, description, 0, iconUri, null, backgroundColor); 73 } 74 75 public static Bundle buildArgs(String title, String breadcrumb, String description, 76 Bitmap iconBitmap) { 77 return buildArgs(title, breadcrumb, description, 0, null, iconBitmap, Color.TRANSPARENT); 78 } 79 80 private static Bundle buildArgs( 81 String title, String breadcrumb, String description, int iconResourceId, 82 Uri iconUri, Bitmap iconBitmap, int iconBackgroundColor) { 83 Bundle args = new Bundle(); 84 args.putString(EXTRA_TITLE, title); 85 args.putString(EXTRA_BREADCRUMB, breadcrumb); 86 args.putString(EXTRA_DESCRIPTION, description); 87 args.putInt(EXTRA_ICON_RESOURCE_ID, iconResourceId); 88 args.putParcelable(EXTRA_ICON_URI, iconUri); 89 args.putParcelable(EXTRA_ICON_BITMAP, iconBitmap); 90 args.putInt(EXTRA_ICON_BACKGROUND, iconBackgroundColor); 91 return args; 92 } 93 94 private final LiteFragment mFragment; 95 private Activity mActivity; 96 private BitmapCallback mBitmapCallBack; 97 private String mTitle; 98 private String mBreadcrumb; 99 private String mDescription; 100 private int mIconResourceId; 101 private Uri mIconUri; 102 private Bitmap mIconBitmap; 103 private int mIconBackgroundColor; 104 private AccessibilityManager mAccessManager; 105 106 public BaseContentFragment(LiteFragment fragment) { 107 mFragment = fragment; 108 } 109 110 public void onCreate(Bundle savedInstanceState) { 111 Bundle state = (savedInstanceState != null) ? savedInstanceState : mFragment.getArguments(); 112 if (mTitle == null) { 113 mTitle = state.getString(EXTRA_TITLE); 114 } 115 if (mBreadcrumb == null) { 116 mBreadcrumb = state.getString(EXTRA_BREADCRUMB); 117 } 118 if (mDescription == null) { 119 mDescription = state.getString(EXTRA_DESCRIPTION); 120 } 121 if (mIconResourceId == 0) { 122 mIconResourceId = state.getInt(EXTRA_ICON_RESOURCE_ID, 0); 123 } 124 if (mIconUri == null) { 125 mIconUri = state.getParcelable(EXTRA_ICON_URI); 126 } 127 if (mIconBitmap == null) { 128 mIconBitmap = state.getParcelable(EXTRA_ICON_BITMAP); 129 } 130 if (mIconBackgroundColor == Color.TRANSPARENT) { 131 mIconBackgroundColor = state.getInt(EXTRA_ICON_BACKGROUND, Color.TRANSPARENT); 132 } 133 } 134 135 public void onSaveInstanceState(Bundle outState) { 136 outState.putString(EXTRA_TITLE, mTitle); 137 outState.putString(EXTRA_BREADCRUMB, mBreadcrumb); 138 outState.putString(EXTRA_DESCRIPTION, mDescription); 139 outState.putInt(EXTRA_ICON_RESOURCE_ID, mIconResourceId); 140 outState.putParcelable(EXTRA_ICON_URI, mIconUri); 141 outState.putParcelable(EXTRA_ICON_BITMAP, mIconBitmap); 142 outState.putInt(EXTRA_ICON_BACKGROUND, mIconBackgroundColor); 143 } 144 145 /** 146 * Pass activity from ContentFragment to BaseContentFragment when it is 147 * attached. 148 */ 149 public void onAttach(Activity activity) { 150 mActivity = activity; 151 } 152 153 /** 154 * Rest BaseContentFragment mActivity to null when ContentFragment is 155 * detached. 156 */ 157 public void onDetach() { 158 mActivity = null; 159 } 160 161 /** 162 * When ContentFragment is winding down / being destroyed, if the 163 * BitmapDownloader is still getting Bitmap for icon ImageView, we should 164 * cancel it. 165 */ 166 public void onDestroyView() { 167 if (mActivity != null 168 && mBitmapCallBack != null) { 169 BitmapDownloader bitmapDownloader = BitmapDownloader.getInstance(mActivity); 170 bitmapDownloader.cancelDownload(mBitmapCallBack); 171 } 172 } 173 174 public View onCreateView( 175 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 176 final View view = inflater.inflate(R.layout.content_fragment, container, false); 177 setText(view, R.id.title, mTitle); 178 setText(view, R.id.breadcrumb, mBreadcrumb); 179 setText(view, R.id.description, mDescription); 180 int iconResourceId = getIconResourceId(); 181 final ImageView iconImageView = (ImageView) view.findViewById(R.id.icon); 182 int iconBackground = getIconBackgroundColor(); 183 if (iconBackground != Color.TRANSPARENT) { 184 iconImageView.setBackgroundColor(iconBackground); 185 } 186 187 if (iconResourceId != 0) { 188 iconImageView.setImageResource(iconResourceId); 189 addShadow(iconImageView, view); 190 updateViewSize(iconImageView); 191 } else { 192 Bitmap iconBitmap = getIconBitmap(); 193 if (iconBitmap != null) { 194 iconImageView.setImageBitmap(iconBitmap); 195 addShadow(iconImageView, view); 196 updateViewSize(iconImageView); 197 } else { 198 Uri iconUri = getIconResourceUri(); 199 if (iconUri != null) { 200 iconImageView.setVisibility(View.INVISIBLE); 201 202 if (mActivity != null) { 203 BitmapDownloader bitmapDownloader = BitmapDownloader.getInstance(mActivity); 204 mBitmapCallBack = new BitmapCallback() { 205 @Override 206 public void onBitmapRetrieved(Bitmap bitmap) { 207 if (bitmap != null) { 208 mIconBitmap = bitmap; 209 iconImageView.setVisibility(View.VISIBLE); 210 iconImageView.setImageBitmap(bitmap); 211 addShadow(iconImageView, view); 212 updateViewSize(iconImageView); 213 } 214 } 215 }; 216 217 bitmapDownloader.getBitmap(new BitmapWorkerOptions.Builder( 218 mActivity).resource(iconUri) 219 .width(iconImageView.getLayoutParams().width).build(), 220 mBitmapCallBack); 221 } 222 } else { 223 iconImageView.setVisibility(View.GONE); 224 } 225 } 226 } 227 228 return view; 229 } 230 231 public ImageView getIcon() { 232 if (mFragment.getView() == null) return null; 233 return (ImageView) mFragment.getView().findViewById(R.id.icon); 234 } 235 236 public TextView getTitle() { 237 if (mFragment.getView() == null) return null; 238 return (TextView) mFragment.getView().findViewById(R.id.title); 239 } 240 241 public Uri getIconResourceUri() { 242 return mIconUri; 243 } 244 245 public int getIconResourceId() { 246 return mIconResourceId; 247 } 248 249 public Bitmap getIconBitmap() { 250 return mIconBitmap; 251 } 252 253 public int getIconBackgroundColor() { 254 return mIconBackgroundColor; 255 } 256 257 public RelativeLayout getRoot() { 258 return (RelativeLayout) mFragment.getView(); 259 } 260 261 public TextView getBreadCrumb() { 262 if (mFragment.getView() == null) return null; 263 return (TextView) mFragment.getView().findViewById(R.id.breadcrumb); 264 } 265 266 public TextView getDescription() { 267 if (mFragment.getView() == null) return null; 268 return (TextView) mFragment.getView().findViewById(R.id.description); 269 } 270 271 public void setTextToExtra(View parent, int textViewResourceId, 272 String extraLabel) { 273 String text = mFragment.getArguments().getString(extraLabel, null); 274 setText(parent, textViewResourceId, text); 275 } 276 277 public void setTextToExtra(int textViewResourceId, String extraLabel) { 278 if (mFragment.getView() == null) return; 279 setTextToExtra(mFragment.getView(), textViewResourceId, extraLabel); 280 } 281 282 public void setText(View parent, int textViewResourceId, String text) { 283 TextView textView = (TextView) parent.findViewById(textViewResourceId); 284 if (textView != null && text != null) { 285 textView.setText(text); 286 287 // Enable focusable title and description if accessibility is enabled. 288 if (mActivity != null) { 289 if (mAccessManager == null) { 290 mAccessManager = (AccessibilityManager) mActivity 291 .getSystemService(Context.ACCESSIBILITY_SERVICE); 292 } 293 if (mAccessManager.isEnabled()) { 294 textView.setFocusable(true); 295 textView.setFocusableInTouchMode(true); 296 } 297 } 298 } 299 } 300 301 public void setText(int textViewResourceId, String text) { 302 if (mFragment.getView() == null) return; 303 setText(mFragment.getView(), textViewResourceId, text); 304 } 305 306 public void setTitleText(String text) { 307 mTitle = text; 308 if (mFragment.getView() == null) return; 309 setText(mFragment.getView(), R.id.title, text); 310 } 311 312 public void setBreadCrumbText(String text) { 313 mBreadcrumb = text; 314 if (mFragment.getView() == null) return; 315 setText(mFragment.getView(), R.id.breadcrumb, text); 316 } 317 318 public void setDescriptionText(String text) { 319 mDescription = text; 320 if (mFragment.getView() == null) return; 321 setText(mFragment.getView(), R.id.description, text); 322 } 323 324 /** 325 * Unlike {@link #setIcon(int)} and {@link #setIcon(Uri)}, this will only work if called 326 * after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. 327 * @param iconDrawable 328 */ 329 public void setIcon(Drawable iconDrawable) { 330 if (mFragment.getView() == null) return; 331 332 final ImageView iconImageView = (ImageView) mFragment.getView().findViewById(R.id.icon); 333 if (iconImageView != null) { 334 if (iconDrawable != null) { 335 iconImageView.setImageDrawable(iconDrawable); 336 iconImageView.setVisibility(View.VISIBLE); 337 updateViewSize(iconImageView); 338 } 339 } 340 } 341 342 public void setIcon(int iconResourceId) { 343 mIconResourceId = iconResourceId; 344 if (mFragment.getView() == null) return; 345 346 final ImageView iconImageView = (ImageView) mFragment.getView().findViewById(R.id.icon); 347 if (iconImageView != null) { 348 if (iconResourceId != 0) { 349 iconImageView.setImageResource(iconResourceId); 350 iconImageView.setVisibility(View.VISIBLE); 351 updateViewSize(iconImageView); 352 } 353 } 354 } 355 356 public void setIcon(Uri iconUri) { 357 mIconUri = iconUri; 358 if (mFragment.getView() == null) return; 359 360 final ImageView iconImageView = (ImageView) mFragment.getView().findViewById(R.id.icon); 361 if (iconImageView != null) { 362 if (iconUri != null) { 363 iconImageView.setVisibility(View.INVISIBLE); 364 365 if (mActivity != null) { 366 BitmapDownloader bitmapDownloader = BitmapDownloader.getInstance(mActivity); 367 mBitmapCallBack = new BitmapCallback() { 368 @Override 369 public void onBitmapRetrieved(Bitmap bitmap) { 370 if (bitmap != null) { 371 mIconBitmap = bitmap; 372 iconImageView.setImageBitmap(bitmap); 373 iconImageView.setVisibility(View.VISIBLE); 374 updateViewSize(iconImageView); 375 fadeIn(iconImageView); 376 addShadow(iconImageView, mFragment.getView()); 377 } 378 } 379 }; 380 381 bitmapDownloader.getBitmap(new BitmapWorkerOptions.Builder(mActivity).resource( 382 iconUri).width(iconImageView.getLayoutParams().width).build(), 383 mBitmapCallBack); 384 } 385 } 386 } 387 } 388 389 private void updateViewSize(ImageView iconView) { 390 int intrinsicWidth = iconView.getDrawable().getIntrinsicWidth(); 391 LayoutParams lp = iconView.getLayoutParams(); 392 if (intrinsicWidth > 0) { 393 lp.height = lp.width * iconView.getDrawable().getIntrinsicHeight() 394 / intrinsicWidth; 395 } else { 396 // If no intrinsic width, then just mke this a square. 397 lp.height = lp.width; 398 } 399 } 400 401 private void addShadow(ImageView icon, View view) { 402 FrameLayoutWithShadows shadowLayout = (FrameLayoutWithShadows) 403 view.findViewById(R.id.shadow_layout); 404 shadowLayout.addShadowView(icon); 405 } 406 407 private void fadeIn(View v) { 408 v.setAlpha(0f); 409 ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(v, "alpha", 1f); 410 alphaAnimator.setDuration(mActivity.getResources().getInteger( 411 android.R.integer.config_mediumAnimTime)); 412 alphaAnimator.start(); 413 } 414 } 415