Prevents ListView items children to modify properties of other children.
Bug #2464502 This fix introduce a new dispatch mechanism to tell views when they are temporary detached/reattached from/to a ListView. This is very important to remove pending callbacks or cleanup temporary states. This change also modifies TextView which was relying on that callback in a very particular case: a focused EditText in a ListView. The modified code acts only when in that case, not if onStart/FinishTemporaryDetach() is called via dispatch*() (== recycled views in ListView.)
This commit is contained in:
@@ -3650,14 +3650,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a container is going to temporarily detach a child
|
||||
* that currently has focus, with
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchStartTemporaryDetach() {
|
||||
onStartTemporaryDetach();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a container is going to temporarily detach a child, with
|
||||
* {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
|
||||
* It will either be followed by {@link #onFinishTemporaryDetach()} or
|
||||
* {@link #onDetachedFromWindow()} when the container is done. Generally
|
||||
* this is currently only done ListView for a view with focus.
|
||||
* {@link #onDetachedFromWindow()} when the container is done.
|
||||
*/
|
||||
public void onStartTemporaryDetach() {
|
||||
removeUnsetPressCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void dispatchFinishTemporaryDetach() {
|
||||
onFinishTemporaryDetach();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4361,6 +4374,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the prepress detection timer.
|
||||
*/
|
||||
private void removeUnsetPressCallback() {
|
||||
if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
|
||||
setPressed(false);
|
||||
removeCallbacks(mUnsetPressedState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the tap detection timer.
|
||||
*/
|
||||
@@ -5886,6 +5909,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
* @see #onAttachedToWindow()
|
||||
*/
|
||||
protected void onDetachedFromWindow() {
|
||||
removeUnsetPressCallback();
|
||||
removeLongPressCallback();
|
||||
destroyDrawingCache();
|
||||
}
|
||||
@@ -8731,7 +8755,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
boolean clampedX, boolean clampedY) {
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A MeasureSpec encapsulates the layout requirements passed from parent to child.
|
||||
* Each MeasureSpec represents a requirement for either the width or the height.
|
||||
@@ -9181,12 +9205,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*/
|
||||
boolean mRecomputeGlobalAttributes;
|
||||
|
||||
/**
|
||||
* Set to true when attributes (like mKeepScreenOn) need to be
|
||||
* recomputed.
|
||||
*/
|
||||
boolean mAttributesChanged;
|
||||
|
||||
/**
|
||||
* Set during a traveral if any views want to keep the screen on.
|
||||
*/
|
||||
|
||||
@@ -1065,6 +1065,32 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void dispatchStartTemporaryDetach() {
|
||||
super.dispatchStartTemporaryDetach();
|
||||
final int count = mChildrenCount;
|
||||
final View[] children = mChildren;
|
||||
for (int i = 0; i < count; i++) {
|
||||
children[i].dispatchStartTemporaryDetach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void dispatchFinishTemporaryDetach() {
|
||||
super.dispatchFinishTemporaryDetach();
|
||||
final int count = mChildrenCount;
|
||||
final View[] children = mChildren;
|
||||
for (int i = 0; i < count; i++) {
|
||||
children[i].dispatchFinishTemporaryDetach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
|
||||
@@ -1314,7 +1314,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
position, -1);
|
||||
}
|
||||
} else {
|
||||
isScrap[0] = true;
|
||||
isScrap[0] = true;
|
||||
child.dispatchFinishTemporaryDetach();
|
||||
}
|
||||
} else {
|
||||
child = mAdapter.getView(position, null, this);
|
||||
@@ -4145,8 +4146,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
|
||||
if (mViewTypeCount == 1) {
|
||||
scrap.dispatchStartTemporaryDetach();
|
||||
mCurrentScrap.add(scrap);
|
||||
} else {
|
||||
scrap.dispatchStartTemporaryDetach();
|
||||
mScrapViews[viewType].add(scrap);
|
||||
}
|
||||
|
||||
@@ -4165,7 +4168,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
|
||||
ArrayList<View> scrapViews = mCurrentScrap;
|
||||
final int count = activeViews.length;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
final View victim = activeViews[i];
|
||||
if (victim != null) {
|
||||
int whichScrap = ((AbsListView.LayoutParams) victim.getLayoutParams()).viewType;
|
||||
@@ -4181,6 +4184,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
if (multipleScraps) {
|
||||
scrapViews = mScrapViews[whichScrap];
|
||||
}
|
||||
victim.dispatchStartTemporaryDetach();
|
||||
scrapViews.add(victim);
|
||||
|
||||
if (hasListener) {
|
||||
|
||||
@@ -1485,7 +1485,6 @@ public class ListView extends AbsListView {
|
||||
}
|
||||
|
||||
// Clear out old views
|
||||
//removeAllViewsInLayout();
|
||||
detachAllViewsFromParent();
|
||||
|
||||
switch (mLayoutMode) {
|
||||
|
||||
@@ -198,6 +198,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
private boolean mFreezesText;
|
||||
private boolean mFrozenWithFocus;
|
||||
private boolean mTemporaryDetach;
|
||||
private boolean mDispatchTemporaryDetach;
|
||||
|
||||
private boolean mEatTouchRelease = false;
|
||||
private boolean mScrolled = false;
|
||||
@@ -6371,14 +6372,27 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
mBlink.postAtTime(mBlink, mShowCursor + BLINK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchFinishTemporaryDetach() {
|
||||
mDispatchTemporaryDetach = true;
|
||||
super.dispatchFinishTemporaryDetach();
|
||||
mDispatchTemporaryDetach = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTemporaryDetach() {
|
||||
mTemporaryDetach = true;
|
||||
super.onStartTemporaryDetach();
|
||||
// Only track when onStartTemporaryDetach() is called directly,
|
||||
// usually because this instance is an editable field in a list
|
||||
if (!mDispatchTemporaryDetach) mTemporaryDetach = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishTemporaryDetach() {
|
||||
mTemporaryDetach = false;
|
||||
super.onFinishTemporaryDetach();
|
||||
// Only track when onStartTemporaryDetach() is called directly,
|
||||
// usually because this instance is an editable field in a list
|
||||
if (!mDispatchTemporaryDetach) mTemporaryDetach = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user