1 /* 2 * Copyright (C) 2019 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 package com.android.wallpaper.picker; 17 18 import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; 19 import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES; 20 21 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.APPLY; 22 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.CUSTOMIZE; 23 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.DELETE; 24 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.EDIT; 25 import static com.android.wallpaper.widget.BottomActionBar.BottomAction.INFORMATION; 26 27 import android.annotation.SuppressLint; 28 import android.app.Activity; 29 import android.app.AlertDialog; 30 import android.app.WallpaperColors; 31 import android.app.WallpaperInfo; 32 import android.app.WallpaperManager; 33 import android.content.ComponentName; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.pm.ActivityInfo; 37 import android.content.pm.ApplicationInfo; 38 import android.content.pm.PackageManager; 39 import android.content.pm.ServiceInfo; 40 import android.graphics.Point; 41 import android.net.Uri; 42 import android.os.Bundle; 43 import android.os.RemoteException; 44 import android.service.wallpaper.IWallpaperConnection; 45 import android.service.wallpaper.WallpaperService; 46 import android.service.wallpaper.WallpaperSettingsActivity; 47 import android.text.TextUtils; 48 import android.util.Log; 49 import android.view.LayoutInflater; 50 import android.view.MotionEvent; 51 import android.view.SurfaceView; 52 import android.view.View; 53 import android.view.ViewGroup; 54 import android.widget.ImageView; 55 56 import androidx.annotation.NonNull; 57 import androidx.annotation.Nullable; 58 import androidx.cardview.widget.CardView; 59 import androidx.constraintlayout.widget.ConstraintLayout; 60 import androidx.constraintlayout.widget.ConstraintSet; 61 import androidx.lifecycle.LiveData; 62 import androidx.slice.Slice; 63 import androidx.slice.widget.SliceLiveData; 64 import androidx.slice.widget.SliceView; 65 66 import com.android.wallpaper.R; 67 import com.android.wallpaper.compat.BuildCompat; 68 import com.android.wallpaper.model.SetWallpaperViewModel; 69 import com.android.wallpaper.util.FullScreenAnimation; 70 import com.android.wallpaper.util.ResourceUtils; 71 import com.android.wallpaper.util.ScreenSizeCalculator; 72 import com.android.wallpaper.util.SizeCalculator; 73 import com.android.wallpaper.util.WallpaperConnection; 74 import com.android.wallpaper.util.WallpaperSurfaceCallback; 75 import com.android.wallpaper.widget.BottomActionBar; 76 import com.android.wallpaper.widget.BottomActionBar.AccessibilityCallback; 77 import com.android.wallpaper.widget.BottomActionBar.BottomSheetContent; 78 import com.android.wallpaper.widget.LockScreenPreviewer; 79 import com.android.wallpaper.widget.WallpaperColorsLoader; 80 81 import java.util.Locale; 82 import java.util.concurrent.ExecutionException; 83 import java.util.concurrent.Future; 84 import java.util.concurrent.TimeUnit; 85 import java.util.concurrent.TimeoutException; 86 87 /** 88 * Fragment which displays the UI for previewing an individual live wallpaper, its attribution 89 * information and settings slices if available. 90 */ 91 public class LivePreviewFragment extends PreviewFragment implements 92 WallpaperConnection.WallpaperConnectionListener { 93 94 public static final String EXTRA_LIVE_WALLPAPER_INFO = "android.live_wallpaper.info"; 95 public static final String KEY_ACTION_DELETE_LIVE_WALLPAPER = "action_delete_live_wallpaper"; 96 97 private static final String TAG = "LivePreviewFragment"; 98 99 /** 100 * Instance of {@link WallpaperConnection} used to bind to the live wallpaper service to show 101 * it in this preview fragment. 102 * @see IWallpaperConnection 103 */ 104 protected WallpaperConnection mWallpaperConnection; 105 protected CardView mHomePreviewCard; 106 protected SurfaceView mWorkspaceSurface; 107 protected WallpaperSurfaceCallback mWallpaperSurfaceCallback; 108 protected WorkspaceSurfaceHolderCallback mWorkspaceSurfaceCallback; 109 protected ViewGroup mLockPreviewContainer; 110 protected LockScreenPreviewer mLockScreenPreviewer; 111 112 private Intent mDeleteIntent; 113 private Intent mSettingsIntent; 114 private SliceView mSettingsSliceView; 115 private LiveData<Slice> mSettingsLiveData; 116 private Point mScreenSize; 117 private ViewGroup mPreviewContainer; 118 private TouchForwardingLayout mTouchForwardingLayout; 119 private SurfaceView mWallpaperSurface; 120 private Future<Integer> mPlaceholderColorFuture; 121 private WallpaperColors mWallpaperColors; 122 123 @Override onCreate(Bundle savedInstanceState)124 public void onCreate(Bundle savedInstanceState) { 125 super.onCreate(savedInstanceState); 126 android.app.WallpaperInfo info = mWallpaper.getWallpaperComponent(); 127 mPlaceholderColorFuture = mWallpaper.computePlaceholderColor(getContext()); 128 129 String deleteAction = getDeleteAction(info); 130 if (!TextUtils.isEmpty(deleteAction)) { 131 mDeleteIntent = new Intent(deleteAction); 132 mDeleteIntent.setPackage(info.getPackageName()); 133 mDeleteIntent.putExtra(EXTRA_LIVE_WALLPAPER_INFO, info); 134 } 135 String settingsActivity = getSettingsActivity(info); 136 if (settingsActivity != null) { 137 mSettingsIntent = new Intent(); 138 mSettingsIntent.setComponent(new ComponentName(info.getPackageName(), 139 settingsActivity)); 140 mSettingsIntent.putExtra(WallpaperSettingsActivity.EXTRA_PREVIEW_MODE, true); 141 PackageManager pm = requireContext().getPackageManager(); 142 ActivityInfo activityInfo = mSettingsIntent.resolveActivityInfo(pm, 0); 143 if (activityInfo == null) { 144 Log.i(TAG, "Couldn't find wallpaper settings activity: " + settingsActivity); 145 mSettingsIntent = null; 146 } 147 } 148 } 149 150 @Nullable getSettingsActivity(WallpaperInfo info)151 protected String getSettingsActivity(WallpaperInfo info) { 152 return info.getSettingsActivity(); 153 } 154 getWallpaperIntent(WallpaperInfo info)155 protected Intent getWallpaperIntent(WallpaperInfo info) { 156 return new Intent(WallpaperService.SERVICE_INTERFACE) 157 .setClassName(info.getPackageName(), info.getServiceName()); 158 } 159 160 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)161 public View onCreateView(LayoutInflater inflater, ViewGroup container, 162 Bundle savedInstanceState) { 163 View view = super.onCreateView(inflater, container, savedInstanceState); 164 165 Activity activity = requireActivity(); 166 mScreenSize = ScreenSizeCalculator.getInstance().getScreenSize( 167 activity.getWindowManager().getDefaultDisplay()); 168 mPreviewContainer = view.findViewById(R.id.live_wallpaper_preview); 169 mTouchForwardingLayout = view.findViewById(R.id.touch_forwarding_layout); 170 171 // Update preview header color which covers toolbar and status bar area. 172 View previewHeader = view.findViewById(R.id.preview_header); 173 previewHeader.setBackgroundColor(activity.getColor(R.color.settingslib_colorSurfaceHeader)); 174 175 // Set aspect ratio on the preview card. 176 ConstraintSet set = new ConstraintSet(); 177 set.clone((ConstraintLayout) mPreviewContainer); 178 String ratio = String.format(Locale.US, "%d:%d", mScreenSize.x, mScreenSize.y); 179 set.setDimensionRatio(mTouchForwardingLayout.getId(), ratio); 180 set.applyTo((ConstraintLayout) mPreviewContainer); 181 182 mHomePreviewCard = mPreviewContainer.findViewById(R.id.wallpaper_full_preview_card); 183 mLockPreviewContainer = mPreviewContainer.findViewById(R.id.lock_screen_preview_container); 184 mLockScreenPreviewer = new LockScreenPreviewer(getLifecycle(), getContext(), 185 mLockPreviewContainer); 186 mLockScreenPreviewer.setDateViewVisibility(!mFullScreenAnimation.isFullScreen()); 187 mFullScreenAnimation.setFullScreenStatusListener( 188 isFullScreen -> { 189 mLockScreenPreviewer.setDateViewVisibility(!isFullScreen); 190 if (!isFullScreen) { 191 mBottomActionBar.focusAccessibilityAction(EDIT); 192 } 193 }); 194 mWallpaperSurface = mHomePreviewCard.findViewById(R.id.wallpaper_surface); 195 mTouchForwardingLayout.setTargetView(mHomePreviewCard); 196 mTouchForwardingLayout.setForwardingEnabled(true); 197 mWorkspaceSurface = mHomePreviewCard.findViewById(R.id.workspace_surface); 198 199 mWorkspaceSurfaceCallback = createWorkspaceSurfaceCallback(mWorkspaceSurface); 200 mWallpaperSurfaceCallback = new WallpaperSurfaceCallback(getContext(), 201 mHomePreviewCard, mWallpaperSurface, mPlaceholderColorFuture, 202 new WallpaperSurfaceCallback.SurfaceListener() { 203 @Override 204 public void onSurfaceCreated() { 205 previewLiveWallpaper(null); 206 } 207 }); 208 209 setUpTabs(view.findViewById(R.id.separated_tabs)); 210 211 view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 212 @Override 213 public void onLayoutChange(View thisView, int left, int top, int right, int bottom, 214 int oldLeft, int oldTop, int oldRight, int oldBottom) { 215 mHomePreviewCard.setRadius(SizeCalculator.getPreviewCornerRadius(activity, 216 mHomePreviewCard.getMeasuredWidth())); 217 view.removeOnLayoutChangeListener(this); 218 } 219 }); 220 221 return view; 222 } 223 224 @Override onViewCreated(@onNull View view, @Nullable Bundle savedInstanceState)225 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 226 super.onViewCreated(view, savedInstanceState); 227 updateWallpaperSurface(); 228 setupCurrentWallpaperPreview(); 229 renderWorkspaceSurface(); 230 } 231 updateWallpaperSurface()232 private void updateWallpaperSurface() { 233 mWallpaperSurface.getHolder().addCallback(mWallpaperSurfaceCallback); 234 mWallpaperSurface.setZOrderMediaOverlay(true); 235 } 236 237 @Override updateScreenPreview(boolean isHomeSelected)238 protected void updateScreenPreview(boolean isHomeSelected) { 239 mWorkspaceSurface.setVisibility(isHomeSelected ? View.VISIBLE : View.INVISIBLE); 240 241 mLockPreviewContainer.setVisibility(isHomeSelected ? View.INVISIBLE : View.VISIBLE); 242 243 mFullScreenAnimation.setIsHomeSelected(isHomeSelected); 244 } 245 setupCurrentWallpaperPreview()246 private void setupCurrentWallpaperPreview() { 247 mHomePreviewCard.setOnTouchListener((v, ev) -> { 248 if (mWallpaperConnection != null && mWallpaperConnection.getEngine() != null) { 249 float scaleRatio = 250 (float) mTouchForwardingLayout.getWidth() / (float) mScreenSize.x; 251 int action = ev.getActionMasked(); 252 if (action == MotionEvent.ACTION_DOWN) { 253 mBottomActionBar.collapseBottomSheetIfExpanded(); 254 } 255 MotionEvent dup = MotionEvent.obtainNoHistory(ev); 256 dup.setLocation(ev.getX() / scaleRatio, ev.getY() / scaleRatio); 257 try { 258 mWallpaperConnection.getEngine().dispatchPointer(dup); 259 if (action == MotionEvent.ACTION_UP) { 260 mWallpaperConnection.getEngine().dispatchWallpaperCommand( 261 WallpaperManager.COMMAND_TAP, 262 (int) ev.getX(), (int) ev.getY(), 0, null); 263 } else if (action == MotionEvent.ACTION_POINTER_UP) { 264 int pointerIndex = ev.getActionIndex(); 265 mWallpaperConnection.getEngine().dispatchWallpaperCommand( 266 WallpaperManager.COMMAND_SECONDARY_TAP, 267 (int) ev.getX(pointerIndex), (int) ev.getY(pointerIndex), 0, null); 268 } 269 } catch (RemoteException e) { 270 Log.e(TAG, "Remote exception of wallpaper connection"); 271 } 272 } 273 return false; 274 }); 275 } 276 277 @Override onDestroyView()278 public void onDestroyView() { 279 super.onDestroyView(); 280 if (mSettingsLiveData != null && mSettingsLiveData.hasObservers() 281 && mSettingsSliceView != null) { 282 mSettingsLiveData.removeObserver(mSettingsSliceView); 283 mSettingsLiveData = null; 284 } 285 if (mWallpaperConnection != null) { 286 mWallpaperConnection.disconnect(); 287 mWallpaperConnection = null; 288 } 289 if (mLockScreenPreviewer != null) { 290 mLockScreenPreviewer.release(); 291 } 292 mWorkspaceSurfaceCallback.cleanUp(); 293 mWorkspaceSurface.getHolder().removeCallback(mWorkspaceSurfaceCallback); 294 mWallpaperSurfaceCallback.cleanUp(); 295 mWallpaperSurface.getHolder().removeCallback(mWallpaperSurfaceCallback); 296 } 297 previewLiveWallpaper(ImageView thumbnailView)298 protected void previewLiveWallpaper(ImageView thumbnailView) { 299 mWallpaperSurface.post(() -> { 300 Activity activity = getActivity(); 301 if (activity == null) { 302 return; 303 } 304 if (mWallpaperSurfaceCallback.getHomeImageWallpaper() != null) { 305 Integer placeholderColor = null; 306 try { 307 placeholderColor = mPlaceholderColorFuture.get(50, TimeUnit.MILLISECONDS); 308 } catch (InterruptedException | ExecutionException | TimeoutException e) { 309 Log.i(TAG, "Couldn't obtain placeholder color", e); 310 } 311 mWallpaper.getThumbAsset(activity.getApplicationContext()) 312 .loadLowResDrawable(activity, 313 mWallpaperSurfaceCallback.getHomeImageWallpaper(), 314 placeholderColor != null 315 ? placeholderColor 316 : ResourceUtils.getColorAttr(activity, 317 android.R.attr.colorBackground), 318 mPreviewBitmapTransformation); 319 } 320 setUpLiveWallpaperPreview(mWallpaper); 321 }); 322 } 323 setUpLiveWallpaperPreview( com.android.wallpaper.model.WallpaperInfo homeWallpaper)324 protected void setUpLiveWallpaperPreview( 325 com.android.wallpaper.model.WallpaperInfo homeWallpaper) { 326 Activity activity = getActivity(); 327 if (activity == null || activity.isFinishing()) { 328 return; 329 } 330 if (mWallpaperConnection != null) { 331 mWallpaperConnection.disconnect(); 332 } 333 334 if (WallpaperConnection.isPreviewAvailable()) { 335 mWallpaperConnection = new WallpaperConnection( 336 getWallpaperIntent(homeWallpaper.getWallpaperComponent()), 337 activity, 338 /* listener= */ this, 339 mWallpaperSurface); 340 341 mWallpaperConnection.setVisibility(true); 342 } else { 343 WallpaperColorsLoader.getWallpaperColors( 344 activity, 345 homeWallpaper.getThumbAsset(activity), 346 colors -> onWallpaperColorsChanged(colors, 0)); 347 } 348 if (mWallpaperConnection != null && !mWallpaperConnection.connect()) { 349 mWallpaperConnection = null; 350 } 351 } 352 renderWorkspaceSurface()353 private void renderWorkspaceSurface() { 354 mWorkspaceSurface.setZOrderMediaOverlay(true); 355 mWorkspaceSurface.getHolder().addCallback(mWorkspaceSurfaceCallback); 356 } 357 358 @Override onBottomActionBarReady(BottomActionBar bottomActionBar)359 protected void onBottomActionBarReady(BottomActionBar bottomActionBar) { 360 super.onBottomActionBarReady(bottomActionBar); 361 mBottomActionBar.showActionsOnly(INFORMATION, DELETE, EDIT, CUSTOMIZE, APPLY); 362 mBottomActionBar.setActionClickListener(APPLY, unused -> onSetWallpaperClicked(null)); 363 mBottomActionBar.bindBottomSheetContentWithAction( 364 new WallpaperInfoContent(getContext()), INFORMATION); 365 366 View separatedTabsContainer = getView().findViewById(R.id.separated_tabs_container); 367 // Update target view's accessibility param since it will be blocked by the bottom sheet 368 // when expanded. 369 mBottomActionBar.setAccessibilityCallback(new AccessibilityCallback() { 370 @Override 371 public void onBottomSheetCollapsed() { 372 mPreviewContainer.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 373 separatedTabsContainer.setImportantForAccessibility( 374 IMPORTANT_FOR_ACCESSIBILITY_YES); 375 } 376 377 @Override 378 public void onBottomSheetExpanded() { 379 mPreviewContainer.setImportantForAccessibility( 380 IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); 381 separatedTabsContainer.setImportantForAccessibility( 382 IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); 383 } 384 }); 385 final Uri uriSettingsSlice = getSettingsSliceUri(mWallpaper.getWallpaperComponent()); 386 if (uriSettingsSlice != null) { 387 mSettingsLiveData = SliceLiveData.fromUri(requireContext(), uriSettingsSlice); 388 mBottomActionBar.bindBottomSheetContentWithAction( 389 new PreviewCustomizeSettingsContent(getContext()), CUSTOMIZE); 390 } else { 391 if (mSettingsIntent != null) { 392 mBottomActionBar.setActionClickListener(CUSTOMIZE, listener -> 393 startActivity(mSettingsIntent)); 394 } else { 395 mBottomActionBar.hideActions(CUSTOMIZE); 396 } 397 } 398 399 if (TextUtils.isEmpty(getDeleteAction(mWallpaper.getWallpaperComponent()))) { 400 mBottomActionBar.hideActions(DELETE); 401 } else { 402 mBottomActionBar.setActionClickListener(DELETE, listener -> 403 showDeleteConfirmDialog()); 404 } 405 mBottomActionBar.show(); 406 // Action buttons are disabled when live wallpaper is not loaded. 407 mBottomActionBar.disableActions(); 408 // Enable buttons if loaded, or wait for it. 409 if (isLoaded()) { 410 mBottomActionBar.enableActions(); 411 } 412 } 413 414 @Override onEngineShown()415 public void onEngineShown() { 416 Activity activity = getActivity(); 417 if (activity == null) { 418 return; 419 } 420 mWallpaperSurfaceCallback.getHomeImageWallpaper().animate() 421 .setStartDelay(250) 422 .setDuration(250) 423 .alpha(0f) 424 .setInterpolator(ALPHA_OUT) 425 .start(); 426 427 if (mBottomActionBar != null) { 428 mBottomActionBar.enableActions(); 429 } 430 } 431 432 @Override onWallpaperColorsChanged(WallpaperColors colors, int displayId)433 public void onWallpaperColorsChanged(WallpaperColors colors, int displayId) { 434 mWallpaperColors = colors; 435 mLockScreenPreviewer.setColor(colors); 436 437 mFullScreenAnimation.setFullScreenTextColor( 438 colors == null || (colors.getColorHints() 439 & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) == 0 440 ? FullScreenAnimation.FullScreenTextColor.LIGHT 441 : FullScreenAnimation.FullScreenTextColor.DARK); 442 } 443 444 @Override isLoaded()445 protected boolean isLoaded() { 446 return mWallpaperConnection != null && mWallpaperConnection.isEngineReady(); 447 } 448 449 @SuppressLint("NewApi") //Already checking with isAtLeastQ getSettingsSliceUri(android.app.WallpaperInfo info)450 protected Uri getSettingsSliceUri(android.app.WallpaperInfo info) { 451 if (BuildCompat.isAtLeastQ()) { 452 return info.getSettingsSliceUri(); 453 } 454 return null; 455 } 456 457 @Override getLayoutResId()458 protected int getLayoutResId() { 459 return R.layout.fragment_live_preview; 460 } 461 462 @Override setCurrentWallpaper(int destination)463 protected void setCurrentWallpaper(int destination) { 464 mWallpaperSetter.setCurrentWallpaper(getActivity(), mWallpaper, null, 465 destination, 0, null, mWallpaperColors, 466 SetWallpaperViewModel.getCallback(mViewModelProvider)); 467 } 468 469 @Nullable getDeleteAction(android.app.WallpaperInfo wallpaperInfo)470 protected String getDeleteAction(android.app.WallpaperInfo wallpaperInfo) { 471 android.app.WallpaperInfo currentInfo = 472 WallpaperManager.getInstance(requireContext()).getWallpaperInfo(); 473 ServiceInfo serviceInfo = wallpaperInfo.getServiceInfo(); 474 if (!isPackagePreInstalled(serviceInfo.applicationInfo)) { 475 Log.d(TAG, "This wallpaper is not pre-installed: " + serviceInfo.name); 476 return null; 477 } 478 479 ServiceInfo currentService = currentInfo == null ? null : currentInfo.getServiceInfo(); 480 // A currently set Live wallpaper should not be deleted. 481 if (currentService != null && TextUtils.equals(serviceInfo.name, currentService.name)) { 482 return null; 483 } 484 485 final Bundle metaData = serviceInfo.metaData; 486 if (metaData != null) { 487 return metaData.getString(KEY_ACTION_DELETE_LIVE_WALLPAPER); 488 } 489 return null; 490 } 491 492 @Override onResume()493 public void onResume() { 494 super.onResume(); 495 if (mWallpaperConnection != null) { 496 mWallpaperConnection.setVisibility(true); 497 } 498 } 499 500 @Override onPause()501 public void onPause() { 502 super.onPause(); 503 if (mWallpaperConnection != null) { 504 mWallpaperConnection.setVisibility(false); 505 } 506 } 507 508 @Override onStop()509 public void onStop() { 510 super.onStop(); 511 if (mWallpaperConnection != null) { 512 mWallpaperConnection.disconnect(); 513 mWallpaperConnection = null; 514 } 515 } 516 showDeleteConfirmDialog()517 private void showDeleteConfirmDialog() { 518 final AlertDialog alertDialog = new AlertDialog.Builder(getContext()) 519 .setMessage(R.string.delete_wallpaper_confirmation) 520 .setOnDismissListener(dialog -> mBottomActionBar.deselectAction(DELETE)) 521 .setPositiveButton(R.string.delete_live_wallpaper, 522 (dialog, which) -> deleteLiveWallpaper()) 523 .setNegativeButton(android.R.string.cancel, null /* listener */) 524 .create(); 525 alertDialog.show(); 526 } 527 deleteLiveWallpaper()528 private void deleteLiveWallpaper() { 529 if (mDeleteIntent != null) { 530 requireContext().startService(mDeleteIntent); 531 finishActivity(/* success= */ false); 532 } 533 } 534 isPackagePreInstalled(ApplicationInfo info)535 private boolean isPackagePreInstalled(ApplicationInfo info) { 536 return info != null && (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 537 } 538 539 private final class PreviewCustomizeSettingsContent extends BottomSheetContent<View> { 540 PreviewCustomizeSettingsContent(Context context)541 private PreviewCustomizeSettingsContent(Context context) { 542 super(context); 543 } 544 545 @Override getViewId()546 public int getViewId() { 547 return R.layout.preview_customize_settings; 548 } 549 550 @Override onViewCreated(View previewPage)551 public void onViewCreated(View previewPage) { 552 mSettingsSliceView = previewPage.findViewById(R.id.settings_slice); 553 mSettingsSliceView.setMode(SliceView.MODE_LARGE); 554 mSettingsSliceView.setScrollable(false); 555 if (mSettingsLiveData != null) { 556 mSettingsLiveData.observeForever(mSettingsSliceView); 557 } 558 } 559 560 @Override onRecreateView(View oldPreviewPage)561 public void onRecreateView(View oldPreviewPage) { 562 super.onRecreateView(oldPreviewPage); 563 if (mSettingsLiveData != null && mSettingsLiveData.hasObservers() 564 && mSettingsSliceView != null) { 565 mSettingsLiveData.removeObserver(mSettingsSliceView); 566 } 567 } 568 } 569 } 570