private void recomputePhotoAndScrollingMetrics() {
    mHeaderHeightPixels = mHeaderBox.getHeight();

    mPhotoHeightPixels = 0;
    if (mHasPhoto) {
      mPhotoHeightPixels = (int) (mPhotoView.getWidth() / PHOTO_ASPECT_RATIO);
      mPhotoHeightPixels = Math.min(mPhotoHeightPixels, mScrollView.getHeight() * 2 / 3);
    }

    ViewGroup.LayoutParams lp;
    lp = mPhotoViewContainer.getLayoutParams();
    if (lp.height != mPhotoHeightPixels) {
      lp.height = mPhotoHeightPixels;
      mPhotoViewContainer.setLayoutParams(lp);
    }

    ViewGroup.MarginLayoutParams mlp =
        (ViewGroup.MarginLayoutParams) mDetailsContainer.getLayoutParams();
    if (mlp.topMargin != mHeaderHeightPixels + mPhotoHeightPixels) {
      mlp.topMargin = mHeaderHeightPixels + mPhotoHeightPixels;
      mDetailsContainer.setLayoutParams(mlp);
    }

    onScrollChanged(0, 0); // trigger scroll handling
  }
  private void initViews() {
    mFABElevation = getResources().getDimensionPixelSize(R.dimen.fab_elevation);
    mMaxHeaderElevation =
        getResources().getDimensionPixelSize(R.dimen.session_detail_max_header_elevation);

    mScrollView = (ObservableScrollView) getActivity().findViewById(R.id.scroll_view);
    mScrollView.addCallbacks(this);
    ViewTreeObserver vto = mScrollView.getViewTreeObserver();
    if (vto.isAlive()) {
      vto.addOnGlobalLayoutListener(mGlobalLayoutListener);
    }

    mScrollViewChild = getActivity().findViewById(R.id.scroll_view_child);
    mScrollViewChild.setVisibility(View.INVISIBLE);

    mDetailsContainer = getActivity().findViewById(R.id.details_container);
    mHeaderBox = getActivity().findViewById(R.id.header_session);
    mTitle = (TextView) getActivity().findViewById(R.id.session_title);
    mSubtitle = (TextView) getActivity().findViewById(R.id.session_subtitle);
    mPhotoViewContainer = getActivity().findViewById(R.id.session_photo_container);
    mPhotoView = (ImageView) getActivity().findViewById(R.id.session_photo);

    mAbstract = (TextView) getActivity().findViewById(R.id.session_abstract);

    mPlusOneIcon = (ImageView) getActivity().findViewById(R.id.gplus_icon_box);
    mTwitterIcon = (ImageView) getActivity().findViewById(R.id.twitter_icon_box);

    // Find view that shows a Videocam icon if the session is being live streamed.
    mLiveStreamVideocamIconAndText =
        (TextView) getActivity().findViewById(R.id.live_stream_videocam_icon_and_text);

    // Find view that shows a play button and some text for the user to watch the session live
    // stream.
    mLiveStreamPlayIconAndText =
        (TextView) getActivity().findViewById(R.id.live_stream_play_icon_and_text);

    mRequirements = (TextView) getActivity().findViewById(R.id.session_requirements);
    mTags = (LinearLayout) getActivity().findViewById(R.id.session_tags);
    mTagsContainer = (ViewGroup) getActivity().findViewById(R.id.session_tags_container);

    ViewCompat.setTransitionName(mPhotoView, SessionDetailConstants.TRANSITION_NAME_PHOTO);

    mAddScheduleButtonContainer = getActivity().findViewById(R.id.add_schedule_button_container);
    mAddScheduleButton =
        (CheckableFloatingActionButton) getActivity().findViewById(R.id.add_schedule_button);

    mNoPlaceholderImageLoader = new ImageLoader(getContext());
    mSpeakersImageLoader = new ImageLoader(getContext(), R.drawable.person_image_empty);
  }
  @Override
  public void onScrollChanged(int deltaX, int deltaY) {
    // Reposition the header bar -- it's normally anchored to the top of the content,
    // but locks to the top of the screen on scroll
    int scrollY = mScrollView.getScrollY();

    float newTop = Math.max(mPhotoHeightPixels, scrollY);
    mHeaderBox.setTranslationY(newTop);
    mAddScheduleButtonContainer.setTranslationY(
        newTop + mHeaderHeightPixels - mAddScheduleButtonContainerHeightPixels / 2);

    float gapFillProgress = 1;
    if (mPhotoHeightPixels != 0) {
      gapFillProgress =
          Math.min(Math.max(UIUtils.getProgress(scrollY, 0, mPhotoHeightPixels), 0), 1);
    }

    ViewCompat.setElevation(mHeaderBox, gapFillProgress * mMaxHeaderElevation);
    ViewCompat.setElevation(
        mAddScheduleButtonContainer, gapFillProgress * mMaxHeaderElevation + mFABElevation);
    ViewCompat.setElevation(
        mAddScheduleButton, gapFillProgress * mMaxHeaderElevation + mFABElevation);

    // Move background photo (parallax effect)
    mPhotoViewContainer.setTranslationY(scrollY * 0.5f);
  }
  @Override
  public void onDestroy() {
    super.onDestroy();
    if (mScrollView == null) {
      return;
    }

    ViewTreeObserver vto = mScrollView.getViewTreeObserver();
    if (vto.isAlive()) {
      vto.removeGlobalOnLayoutListener(mGlobalLayoutListener);
    }
  }