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
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index 970683b..5019fdf 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -34,6 +34,7 @@
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.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 @@
private CalculatorResult mResultText;
private HorizontalScrollView mFormulaContainer;
private DragLayout mDragLayout;
- private FrameLayout mHistoryFrame;
private ViewPager mPadViewPager;
private View mDeleteButton;
@@ -280,8 +279,6 @@
// 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 @@
mDragLayout.addDragCallback(this);
mDragLayout.setCloseCallback(this);
- mHistoryFrame = (FrameLayout) findViewById(R.id.history_frame);
-
mFormulaText.setOnContextMenuClickListener(mOnFormulaContextMenuClickListener);
mFormulaText.setOnDisplayMemoryOperationsListener(mOnDisplayMemoryOperationsListener);
@@ -596,8 +591,10 @@
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 @@
@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 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 @@
/* 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 @@
return mDisplayView.getMeasuredHeight();
}
- @Override
- public void onLayout(int translation) {
- mHistoryFrame.setTranslationY(translation + mDisplayView.getBottom());
- }
-
/* End override DragCallback methods */
/**
@@ -1358,27 +1351,34 @@
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();
- manager.beginTransaction()
- .replace(R.id.history_frame, mHistoryFragment, HistoryFragment.TAG)
- .addToBackStack(HistoryFragment.TAG)
- .commit();
- manager.executePendingTransactions();
+ stopActionModeOrContextMenu();
+ manager.beginTransaction()
+ .replace(R.id.history_frame, new HistoryFragment(), HistoryFragment.TAG)
+ .setTransition(transit)
+ .addToBackStack(HistoryFragment.TAG)
+ .commit();
- // When HistoryFragment is visible, hide all descendants of the main Calculator view.
- mMainCalculator.setImportantForAccessibility(
- View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
- }
+ // 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
}