@Override
  public void onFinishInflate() {
    setKeyboardHeightRatio(100);

    setupImageButton(getWidenButton(), R.raw.hardware__function__close);
    setupImageButton(getHardwareCompositionButton(), R.raw.qwerty__function__kana__icon);

    leftFrameStubProxy.initialize(
        this,
        R.id.stub_left_frame,
        R.id.left_frame,
        R.id.dropshadow_left_short_top,
        R.id.dropshadow_left_long_top,
        R.id.left_adjust_button,
        R.raw.adjust_arrow_left,
        1.0f,
        R.id.left_dropshadow_short,
        R.id.left_dropshadow_long);
    rightFrameStubProxy.initialize(
        this,
        R.id.stub_right_frame,
        R.id.right_frame,
        R.id.dropshadow_right_short_top,
        R.id.dropshadow_right_long_top,
        R.id.right_adjust_button,
        R.raw.adjust_arrow_right,
        0.0f,
        R.id.right_dropshadow_short,
        R.id.right_dropshadow_long);
  }
  /**
   * Sets {@code LayoutAdjustment} and {@code narrowMode}.
   *
   * <p>They are highly dependent on one another so this method sets both at the same time. This
   * decision makes caller-side simpler.
   */
  public void setLayoutAdjustmentAndNarrowMode(
      LayoutAdjustment layoutAdjustment, boolean narrowMode) {
    checkInflated();

    this.layoutAdjustment = layoutAdjustment;
    this.narrowMode = narrowMode;

    // If on narrowMode, the view is always shown with full-width regard less of given
    // layoutAdjustment.
    LayoutAdjustment temporaryAdjustment = narrowMode ? LayoutAdjustment.FILL : layoutAdjustment;

    View view = getForegroundFrame();
    FrameLayout.LayoutParams layoutParams =
        FrameLayout.LayoutParams.class.cast(view.getLayoutParams());
    Resources resources = getResources();
    layoutParams.width =
        temporaryAdjustment == LayoutAdjustment.FILL
            ? resources.getDisplayMetrics().widthPixels
            : getSideAdjustedWidth();
    layoutParams.gravity = Gravity.BOTTOM;
    if (temporaryAdjustment == LayoutAdjustment.LEFT) {
      layoutParams.gravity |= Gravity.LEFT;
    } else if (temporaryAdjustment == LayoutAdjustment.RIGHT) {
      layoutParams.gravity |= Gravity.RIGHT;
    }
    view.setLayoutParams(layoutParams);

    leftFrameStubProxy.setFrameVisibility(
        temporaryAdjustment == LayoutAdjustment.RIGHT ? VISIBLE : GONE);
    rightFrameStubProxy.setFrameVisibility(
        temporaryAdjustment == LayoutAdjustment.LEFT ? VISIBLE : GONE);

    // Set candidate and desciption text size.
    float candidateTextSize =
        layoutAdjustment == LayoutAdjustment.FILL
            ? resources.getDimension(R.dimen.candidate_text_size)
            : resources.getDimension(R.dimen.candidate_text_size_aligned_layout);
    float descriptionTextSize =
        layoutAdjustment == LayoutAdjustment.FILL
            ? resources.getDimension(R.dimen.candidate_description_text_size)
            : resources.getDimension(R.dimen.candidate_description_text_size_aligned_layout);
    getCandidateView().setCandidateTextDimension(candidateTextSize, descriptionTextSize);
    getSymbolInputView().setCandidateTextDimension(candidateTextSize, descriptionTextSize);
    getConversionCandidateWordContainerView().setCandidateTextDimension(candidateTextSize);

    // In narrow mode, hide software keyboard and show narrow status bar.
    getCandidateView().setNarrowMode(narrowMode);
    if (narrowMode) {
      getKeyboardFrame().setVisibility(GONE);
      getNarrowFrame().setVisibility(VISIBLE);
    } else {
      getKeyboardFrame().setVisibility(VISIBLE);
      getNarrowFrame().setVisibility(GONE);
      resetKeyboardFrameVisibility();
    }

    updateInputFrameHeight();
    updateBackgroundColor();
  }
 void collapseDropShadowAndBackground() {
   leftFrameStubProxy.flipDropShadowVisibility(VISIBLE);
   rightFrameStubProxy.flipDropShadowVisibility(VISIBLE);
   getDropShadowTop().setVisibility(fullscreenMode ? VISIBLE : INVISIBLE);
   getResources();
   setLayoutHeight(
       getBottomBackground(),
       getInputFrameHeight() + (fullscreenMode ? dimensionPixelSize.translucentBorderHeight : 0));
   isDropShadowExpanded = false;
 }
 void expandDropShadowAndBackground() {
   leftFrameStubProxy.flipDropShadowVisibility(INVISIBLE);
   rightFrameStubProxy.flipDropShadowVisibility(INVISIBLE);
   getDropShadowTop().setVisibility(VISIBLE);
   getResources();
   setLayoutHeight(
       getBottomBackground(),
       imeWindowHeight - (fullscreenMode ? 0 : dimensionPixelSize.translucentBorderHeight));
   isDropShadowExpanded = true;
 }
  /**
   * Reset components depending inputFrameHeight or imeWindowHeight. This should be called when
   * inputFrameHeight and/or imeWindowHeight are updated.
   */
  void resetHeightDependingComponents() {
    // Create In/Out animation which dropshadows share between CandidateView and SymbolInputView.
    {
      CandidateView candidateView = getCandidateView();
      int windowHeight = imeWindowHeight;
      int inputFrameHeight = getInputFrameHeight();
      int candidateViewHeight = windowHeight - inputFrameHeight;
      long duration = getResources().getInteger(R.integer.candidate_frame_transition_duration);
      float fromAlpha = 0.0f;
      float toAlpha = 1.0f;

      candidateViewInAnimation =
          createCandidateViewTransitionAnimation(
              candidateViewHeight, 0, fromAlpha, toAlpha, duration);
      candidateView.setInAnimation(candidateViewInAnimation);
      dropShadowCandidateViewInAnimation =
          createAlphaAnimation(1.0f - fromAlpha, 1.0f - toAlpha, duration);

      candidateViewOutAnimation =
          createCandidateViewTransitionAnimation(
              0, candidateViewHeight, toAlpha, fromAlpha, duration);
      candidateView.setOutAnimation(candidateViewOutAnimation);
      dropShadowCandidateViewOutAnimation =
          createAlphaAnimation(1.0f - toAlpha, 1.0f - fromAlpha, duration);
    }

    SymbolInputView symbolInputView = getSymbolInputView();
    {
      long duration = getResources().getInteger(R.integer.symbol_input_transition_duration_in);
      float fromAlpha = 0.3f;
      float toAlpha = 1.0f;

      symbolInputViewInAnimation = createAlphaAnimation(fromAlpha, toAlpha, duration);
      symbolInputView.setInAnimation(symbolInputViewInAnimation);
      dropShadowSymbolInputViewInAnimation =
          createAlphaAnimation(1.0f - fromAlpha, 1.0f - toAlpha, duration);

      symbolInputViewOutAnimation = createAlphaAnimation(toAlpha, fromAlpha, duration);
      symbolInputView.setOutAnimation(symbolInputViewOutAnimation);
      dropShadowSymbolInputViewOutAnimation =
          createAlphaAnimation(1.0f - toAlpha, 1.0f - fromAlpha, duration);
    }

    // Reset drop shadow height.
    int shortHeight = getInputFrameHeight() + dimensionPixelSize.translucentBorderHeight;
    int longHeight = imeWindowHeight;
    leftFrameStubProxy.setDropShadowHeight(shortHeight, longHeight);
    rightFrameStubProxy.setDropShadowHeight(shortHeight, longHeight);

    // Reset side adjust buttons height.
    leftFrameStubProxy.resetAdjustButtonBottomMargin(getInputFrameHeight());
    rightFrameStubProxy.resetAdjustButtonBottomMargin(getInputFrameHeight());
  }
 void startDropShadowAnimation(Animation mainAnimation, Animation subAnimation) {
   leftFrameStubProxy.startDropShadowAnimation(subAnimation, mainAnimation);
   rightFrameStubProxy.startDropShadowAnimation(subAnimation, mainAnimation);
   getDropShadowTop().startAnimation(mainAnimation);
 }
  public void setEventListener(
      final ViewEventListener viewEventListener,
      OnClickListener widenButtonClickListener,
      OnClickListener leftAdjustButtonClickListener,
      OnClickListener rightAdjustButtonClickListener) {
    checkInflated();

    // Propagate the given listener into the child views.
    // Set CandidateViewListener as well here, because it uses viewEventListener.
    Resources resources = getResources();
    int foldOvershootDurationRate =
        resources.getInteger(R.integer.input_frame_fold_overshoot_duration_rate);
    int foldOvershootRate = resources.getInteger(R.integer.input_frame_fold_overshoot_rate);
    int expandOvershootDurationRate =
        resources.getInteger(R.integer.input_frame_expand_overshoot_duration_rate);
    int expandOvershootRate = resources.getInteger(R.integer.input_frame_expand_overshoot_rate);
    getCandidateView()
        .setViewEventListener(
            viewEventListener,
            new InputFrameFoldButtonClickListener(
                viewEventListener,
                getKeyboardFrame(),
                resources.getInteger(R.integer.input_frame_fold_duration),
                SequentialInterpolator.newBuilder()
                    .add(
                        new DecelerateInterpolator(),
                        foldOvershootDurationRate,
                        -foldOvershootRate / 1e6f)
                    .add(new AccelerateInterpolator(), 1e6f - foldOvershootDurationRate, 1)
                    .build(),
                resources.getInteger(R.integer.input_frame_expand_duration),
                SequentialInterpolator.newBuilder()
                    .add(
                        new DecelerateInterpolator(),
                        expandOvershootDurationRate,
                        1 + expandOvershootRate / 1e6f)
                    .add(
                        new AccelerateDecelerateInterpolator(),
                        1e6f - expandOvershootDurationRate,
                        1)
                    .build(),
                new LayoutParamsAnimator(new Handler(Looper.myLooper())),
                resources.getInteger(R.integer.input_frame_snap_velocity_threshold) / 1e3f));

    getSymbolInputView()
        .setViewEventListener(
            viewEventListener,
            /** Click handler of the close button. */
            new OnClickListener() {
              @Override
              public void onClick(View v) {
                if (viewEventListener != null) {
                  viewEventListener.onFireFeedbackEvent(FeedbackEvent.INPUTVIEW_FOLD);
                }
                startSymbolInputViewOutAnimation();
              }
            });

    getHardwareCompositionButton()
        .setOnClickListener(
            new OnClickListener() {
              @Override
              public void onClick(View v) {
                viewEventListener.onHardwareKeyboardCompositionModeChange(
                    CompositionSwitchMode.TOGGLE);
              }
            });

    getWidenButton().setOnClickListener(widenButtonClickListener);

    leftFrameStubProxy.setButtonOnClickListener(leftAdjustButtonClickListener);
    rightFrameStubProxy.setButtonOnClickListener(rightAdjustButtonClickListener);
  }