Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39297788 authored by Justin Klaassen's avatar Justin Klaassen
Browse files

Don't re-use mHistoryFragment

Make a new HistoryFragment every time we enter and exit history to work
around a bug on older platforms where a Fragment's internal state may
not be reset correctly when detached.

Also the HistoryFragment open/close transition is now properly animated
using a custom Animator returned by DragLayout.

Fixes: 33587141
Fixes: 33789131
Fixes: 33789337
Fixes: 34132294
Fixes: 34132998
Fixes: 34134349
Fixes: 34135442

Test: manually verified no crash occurs on API 22, 23, & 24 emulator
Change-Id: Iaefbe2bbf4ca186b6396397579887774ed5906d3
parent a9395c92
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
    <FrameLayout
        android:id="@+id/history_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
        android:layout_height="match_parent"
        android:visibility="invisible" />

</com.android.calculator2.DragLayout>
+3 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/display_background_color"
    android:clipChildren="false"
    android:orientation="vertical">

@@ -40,9 +39,12 @@
        android:id="@+id/history_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/display_background_color"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingBottom="@dimen/history_divider_padding"
        android:visibility="invisible"
        app:layoutManager="LinearLayoutManager"
        app:reverseLayout="true" />

</LinearLayout>
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
    android:paddingTop="@dimen/history_divider_padding"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:importantForAccessibility="no"
    android:orientation="vertical">

    <View
+37 −37
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.animation.PropertyValuesHolder;
import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.ClipData;
import android.content.DialogInterface;
import android.content.Intent;
@@ -66,7 +67,6 @@ import android.view.ViewAnimationUtils;
import android.view.ViewGroupOverlay;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.TextView;
import android.widget.Toolbar;
@@ -252,7 +252,6 @@ public class Calculator extends Activity
    private CalculatorResult mResultText;
    private HorizontalScrollView mFormulaContainer;
    private DragLayout mDragLayout;
    private FrameLayout mHistoryFrame;

    private ViewPager mPadViewPager;
    private View mDeleteButton;
@@ -280,8 +279,6 @@ public class Calculator extends Activity
    // Whether the display is one line.
    private boolean mIsOneLine;

    private HistoryFragment mHistoryFragment = new HistoryFragment();

    /**
     * Map the old saved state to a new state reflecting requested result reevaluation.
     */
@@ -421,8 +418,6 @@ public class Calculator extends Activity
        mDragLayout.addDragCallback(this);
        mDragLayout.setCloseCallback(this);

        mHistoryFrame = (FrameLayout) findViewById(R.id.history_frame);

        mFormulaText.setOnContextMenuClickListener(mOnFormulaContextMenuClickListener);
        mFormulaText.setOnDisplayMemoryOperationsListener(mOnDisplayMemoryOperationsListener);

@@ -596,8 +591,10 @@ public class Calculator extends Activity
    public boolean dispatchTouchEvent(MotionEvent e) {
        if (e.getActionMasked() == MotionEvent.ACTION_DOWN) {
            stopActionModeOrContextMenu();
            if (mDragLayout.isOpen()) {
                mHistoryFragment.stopActionModeOrContextMenu();

            final HistoryFragment historyFragment = getHistoryFragment();
            if (mDragLayout.isOpen() && historyFragment != null) {
                historyFragment.stopActionModeOrContextMenu();
            }
        }
        return super.dispatchTouchEvent(e);
@@ -606,9 +603,9 @@ public class Calculator extends Activity
    @Override
    public void onBackPressed() {
        if (!stopActionModeOrContextMenu()) {
            if (mDragLayout.isOpen()) {
                if (!mHistoryFragment.stopActionModeOrContextMenu()) {
                    mDragLayout.setClosed();
            final HistoryFragment historyFragment = getHistoryFragment();
            if (mDragLayout.isOpen() && historyFragment != null) {
                if (!historyFragment.stopActionModeOrContextMenu()) {
                    removeHistoryFragment();
                }
                return;
@@ -1278,8 +1275,7 @@ public class Calculator extends Activity
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_history:
                showHistoryFragment();
                mDragLayout.setOpen();
                showHistoryFragment(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                return true;
            case R.id.menu_leading:
                displayFull();
@@ -1306,21 +1302,23 @@ public class Calculator extends Activity

    /* Begin override DragCallback methods */

    @Override
    public void onStartDraggingOpen() {
        showHistoryFragment();
        mDisplayView.hideToolbar();
        showHistoryFragment(FragmentTransaction.TRANSIT_NONE);
    }

    @Override
    public void onInstanceStateRestored(boolean isOpen) {
    }

    @Override
    public void whileDragging(float yFraction) {
        // no-op
    }

    @Override
    public boolean shouldCaptureView(View view, int x, int y) {
        return mDragLayout.isMoving()
                || mDragLayout.isOpen()
                || mDragLayout.isViewUnder(mDisplayView, x, y);
        return view.getId() == R.id.history_frame
            && (mDragLayout.isMoving() || mDragLayout.isViewUnder(view, x, y));
    }

    @Override
@@ -1328,11 +1326,6 @@ public class Calculator extends Activity
        return mDisplayView.getMeasuredHeight();
    }

    @Override
    public void onLayout(int translation) {
        mHistoryFrame.setTranslationY(translation + mDisplayView.getBottom());
    }

    /* End override DragCallback methods */

    /**
@@ -1358,27 +1351,34 @@ public class Calculator extends Activity
        return true;
    }

    private void showHistoryFragment() {
    private HistoryFragment getHistoryFragment() {
        final FragmentManager manager = getFragmentManager();
        if (manager == null || manager.isDestroyed()) {
            return null;
        }
        return (HistoryFragment) manager.findFragmentByTag(HistoryFragment.TAG);
    }

    private void showHistoryFragment(int transit) {
        final FragmentManager manager = getFragmentManager();
        if (manager == null || manager.isDestroyed()) {
            return;
        }
        if (!prepareForHistory()) {

        if (getHistoryFragment() != null || !prepareForHistory()) {
            return;
        }
        if (!mDragLayout.isOpen()) {
            stopActionModeOrContextMenu();

        stopActionModeOrContextMenu();
        manager.beginTransaction()
                    .replace(R.id.history_frame, mHistoryFragment, HistoryFragment.TAG)
                .replace(R.id.history_frame, new HistoryFragment(), HistoryFragment.TAG)
                .setTransition(transit)
                .addToBackStack(HistoryFragment.TAG)
                .commit();
            manager.executePendingTransactions();

        // When HistoryFragment is visible, hide all descendants of the main Calculator view.
        mMainCalculator.setImportantForAccessibility(
                View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
        }
        // TODO: pass current scroll position of result
    }

+47 −47
Original line number Diff line number Diff line
@@ -94,9 +94,17 @@ public final class DragController {
    }

    public void animateViews(float yFraction, RecyclerView recyclerView) {
        final HistoryAdapter.ViewHolder vh = (HistoryAdapter.ViewHolder)
                recyclerView.findViewHolderForAdapterPosition(0);
        if (yFraction > 0) {
        if (mDisplayFormula == null
                || mDisplayResult == null
                || mToolbar == null
                || mEvaluator == null) {
            // Bail if we aren't yet initialized.
            return;
        }

        final HistoryAdapter.ViewHolder vh =
                (HistoryAdapter.ViewHolder) recyclerView.findViewHolderForAdapterPosition(0);
        if (yFraction > 0 && vh != null) {
            recyclerView.setVisibility(View.VISIBLE);
        }
        if (vh != null && !EvaluatorStateUtils.isDisplayEmpty(mEvaluator)) {
@@ -123,7 +131,6 @@ public final class DragController {
                mAnimationInitialized = true;
            }

            if (mAnimationInitialized) {
            result.setScaleX(mAnimationController.getResultScale(yFraction));
            result.setScaleY(mAnimationController.getResultScale(yFraction));

@@ -150,13 +157,11 @@ public final class DragController {

            date.setTranslationY(mAnimationController.getDateTranslationY(yFraction));
            divider.setTranslationY(mAnimationController.getDateTranslationY(yFraction));
            }
        } else if (EvaluatorStateUtils.isDisplayEmpty(mEvaluator)) {
            // There is no current expression but we still need to collect information
            // to translate the other viewholders.
            if (!mAnimationInitialized) {
                mAnimationController.initializeDisplayHeight();

                mAnimationInitialized = true;
            }
        }
@@ -180,11 +185,8 @@ public final class DragController {

    /**
     * Reset all initialized values.
     * If the DragLayout is closed, set recyclerview to INVISIBLE to avoid flickering.
     */
    public void initializeAnimation(RecyclerView recyclerView, boolean isResult,
            boolean oneLine, boolean isOpen) {
        recyclerView.setVisibility(isOpen ? View.VISIBLE : View.INVISIBLE);
    public void initializeAnimation(boolean isResult, boolean oneLine) {
        mAnimationInitialized = false;
        initializeController(isResult, oneLine);
    }
@@ -245,7 +247,7 @@ public final class DragController {

        public void initializeScales(AlignedTextView formula, CalculatorResult result) {
            // Calculate the scale for the text
            mFormulaScale = (mDisplayFormula.getTextSize() * 1.0f) / formula.getTextSize();
            mFormulaScale = mDisplayFormula.getTextSize() / formula.getTextSize();
        }

        public void initializeFormulaTranslationY(AlignedTextView formula,
@@ -281,38 +283,37 @@ public final class DragController {
        }

        public float getResultTranslationX(float yFraction) {
            return (mResultTranslationX * yFraction) - mResultTranslationX;
            return mResultTranslationX * (yFraction - 1f);
        }

        public float getResultTranslationY(float yFraction) {
            return (mResultTranslationY * yFraction) - mResultTranslationY;
            return mResultTranslationY * (yFraction - 1f);
        }

        public float getResultScale(float yFraction) {
            return 1;
            return 1f;
        }

        public float getFormulaScale(float yFraction) {
            return mFormulaScale - (mFormulaScale * yFraction) + yFraction;
            return mFormulaScale + (1f - mFormulaScale) * yFraction;
        }

        public float getFormulaTranslationX(float yFraction) {
            return (mFormulaTranslationX * yFraction) -
                    mFormulaTranslationX;
            return mFormulaTranslationX * (yFraction - 1f);
        }

        public float getFormulaTranslationY(float yFraction) {
            // Scale linearly between -FormulaTranslationY and 0.
            return (mFormulaTranslationY * yFraction) - mFormulaTranslationY;
            return mFormulaTranslationY * (yFraction - 1f);
        }

        public float getDateTranslationY(float yFraction) {
            // We also want the date to start out above the visible screen with
            // this distance decreasing as it's pulled down.
            // Account for the scaled formula height.
            return -mToolbar.getHeight() * (1 - yFraction)
            return -mToolbar.getHeight() * (1f - yFraction)
                    + getFormulaTranslationY(yFraction)
                    - mDisplayFormula.getHeight() /getFormulaScale(yFraction) * (1 - yFraction);
                    - mDisplayFormula.getHeight() /getFormulaScale(yFraction) * (1f - yFraction);
        }

        public float getHistoryElementTranslationY(float yFraction) {
@@ -331,8 +332,7 @@ public final class DragController {
        public void initializeScales(AlignedTextView formula, CalculatorResult result) {
            final float textSize = mDisplayResult.getTextSize() * mDisplayResult.getScaleX();
            mResultScale = textSize / result.getTextSize();

            mFormulaScale = 1;
            mFormulaScale = 1f;
        }

        @Override
@@ -392,14 +392,14 @@ public final class DragController {

        @Override
        public float getFormulaScale(float yFraction) {
            return 1;
            return 1f;
        }

        @Override
        public float getDateTranslationY(float yFraction) {
            // We also want the date to start out above the visible screen with
            // this distance decreasing as it's pulled down.
            return -mToolbar.getHeight() * (1 - yFraction)
            return -mToolbar.getHeight() * (1f - yFraction)
                    + (mResultTranslationY * yFraction) - mResultTranslationY
                    - mDisplayFormula.getPaddingTop() +
                    (mDisplayFormula.getPaddingTop() * yFraction);
@@ -448,27 +448,27 @@ public final class DragController {

        @Override
        public float getResultTranslationX(float yFraction) {
            return 0;
            return 0f;
        }

        @Override
        public float getResultTranslationY(float yFraction) {
            return 0;
            return 0f;
        }

        @Override
        public float getFormulaScale(float yFraction) {
            return 1;
            return 1f;
        }

        @Override
        public float getDateTranslationY(float yFraction) {
            return 0;
            return 0f;
        }

        @Override
        public float getHistoryElementTranslationY(float yFraction) {
            return -mDisplayHeight * (1 - yFraction) - mBottomPaddingHeight;
            return -mDisplayHeight * (1f - yFraction) - mBottomPaddingHeight;
        }

        @Override
Loading