mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 11:42:04 +08:00
fix(android): ScrollView BadParcelableException (#10213)
This commit is contained in:

committed by
GitHub

parent
0183f7e643
commit
a26a03eeb8
Binary file not shown.
@ -223,8 +223,9 @@ public class GridLayout extends LayoutBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeFromMap(View child) {
|
private void removeFromMap(View child) {
|
||||||
this.map.get(child).child = null;
|
if (this.map.containsKey(child)) {
|
||||||
this.map.remove(child);
|
this.map.remove(child).child = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,17 +2,13 @@ package org.nativescript.widgets;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewParent;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author hhristov
|
* @author hhristov
|
||||||
*/
|
*/
|
||||||
@ -23,7 +19,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
|||||||
private int contentMeasuredWidth = 0;
|
private int contentMeasuredWidth = 0;
|
||||||
private int contentMeasuredHeight = 0;
|
private int contentMeasuredHeight = 0;
|
||||||
private int scrollableLength = 0;
|
private int scrollableLength = 0;
|
||||||
private SavedState mSavedState;
|
private ScrollSavedState mSavedState;
|
||||||
private boolean isFirstLayout = true;
|
private boolean isFirstLayout = true;
|
||||||
private boolean scrollEnabled = true;
|
private boolean scrollEnabled = true;
|
||||||
|
|
||||||
@ -180,7 +176,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
|||||||
|
|
||||||
this.mIsLayoutDirty = false;
|
this.mIsLayoutDirty = false;
|
||||||
// Give a child focus if it needs it
|
// Give a child focus if it needs it
|
||||||
if (this.mChildToScrollTo != null && isViewDescendantOf(this.mChildToScrollTo, this)) {
|
if (this.mChildToScrollTo != null && Utils.isViewDescendantOf(this.mChildToScrollTo, this)) {
|
||||||
this.scrollToChild(this.mChildToScrollTo);
|
this.scrollToChild(this.mChildToScrollTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +190,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
|||||||
|
|
||||||
final int scrollRange = Math.max(0, childWidth - (right - left - this.getPaddingLeft() - this.getPaddingRight()));
|
final int scrollRange = Math.max(0, childWidth - (right - left - this.getPaddingLeft() - this.getPaddingRight()));
|
||||||
if (this.mSavedState != null) {
|
if (this.mSavedState != null) {
|
||||||
scrollX = (this.isLayoutRtl() == mSavedState.isLayoutRtl) ? mSavedState.scrollPosition : (scrollRange - this.mSavedState.scrollPosition);
|
scrollX = this.isLayoutRtl() ? scrollRange - mSavedState.scrollOffsetFromStart : mSavedState.scrollOffsetFromStart;
|
||||||
mSavedState = null;
|
mSavedState = null;
|
||||||
} else {
|
} else {
|
||||||
if (this.isLayoutRtl()) {
|
if (this.isLayoutRtl()) {
|
||||||
@ -228,7 +224,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRestoreInstanceState(Parcelable state) {
|
protected void onRestoreInstanceState(Parcelable state) {
|
||||||
SavedState ss = (SavedState) state;
|
ScrollSavedState ss = (ScrollSavedState) state;
|
||||||
super.onRestoreInstanceState(ss.getSuperState());
|
super.onRestoreInstanceState(ss.getSuperState());
|
||||||
this.mSavedState = ss;
|
this.mSavedState = ss;
|
||||||
this.requestLayout();
|
this.requestLayout();
|
||||||
@ -237,9 +233,8 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
|||||||
@Override
|
@Override
|
||||||
protected Parcelable onSaveInstanceState() {
|
protected Parcelable onSaveInstanceState() {
|
||||||
Parcelable superState = super.onSaveInstanceState();
|
Parcelable superState = super.onSaveInstanceState();
|
||||||
SavedState ss = new SavedState(superState);
|
ScrollSavedState ss = new ScrollSavedState(superState);
|
||||||
ss.scrollPosition = this.getScrollX();
|
ss.scrollOffsetFromStart = isLayoutRtl() ? -this.getScrollX() : this.getScrollX();
|
||||||
ss.isLayoutRtl = this.isLayoutRtl();
|
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,58 +253,4 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
|
|||||||
private boolean isLayoutRtl() {
|
private boolean isLayoutRtl() {
|
||||||
return (this.getLayoutDirection() == LAYOUT_DIRECTION_RTL);
|
return (this.getLayoutDirection() == LAYOUT_DIRECTION_RTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if child is a descendant of parent, (or equal to the parent).
|
|
||||||
*/
|
|
||||||
static boolean isViewDescendantOf(View child, View parent) {
|
|
||||||
if (child == parent) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ViewParent theParent = child.getParent();
|
|
||||||
return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SavedState extends BaseSavedState {
|
|
||||||
public int scrollPosition;
|
|
||||||
public boolean isLayoutRtl;
|
|
||||||
|
|
||||||
SavedState(Parcelable superState) {
|
|
||||||
super(superState);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SavedState(Parcel source) {
|
|
||||||
super(source);
|
|
||||||
scrollPosition = source.readInt();
|
|
||||||
isLayoutRtl = source.readInt() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
super.writeToParcel(dest, flags);
|
|
||||||
dest.writeInt(scrollPosition);
|
|
||||||
dest.writeInt(isLayoutRtl ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "HorizontalScrollView.SavedState{"
|
|
||||||
+ Integer.toHexString(System.identityHashCode(this))
|
|
||||||
+ " scrollPosition=" + scrollPosition
|
|
||||||
+ " isLayoutRtl=" + isLayoutRtl + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Creator<SavedState> CREATOR
|
|
||||||
= new Creator<SavedState>() {
|
|
||||||
public SavedState createFromParcel(Parcel in) {
|
|
||||||
return new SavedState(in);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SavedState[] newArray(int size) {
|
|
||||||
return new SavedState[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package org.nativescript.widgets;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import android.view.View.BaseSavedState;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author CatchABus
|
||||||
|
*/
|
||||||
|
class ScrollSavedState extends BaseSavedState {
|
||||||
|
public int scrollOffsetFromStart;
|
||||||
|
|
||||||
|
ScrollSavedState(Parcelable superState) {
|
||||||
|
super(superState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollSavedState(Parcel source) {
|
||||||
|
super(source);
|
||||||
|
scrollOffsetFromStart = source.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.N)
|
||||||
|
public ScrollSavedState(Parcel source, ClassLoader loader) {
|
||||||
|
super(source, loader);
|
||||||
|
scrollOffsetFromStart = source.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
super.writeToParcel(dest, flags);
|
||||||
|
dest.writeInt(scrollOffsetFromStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ScrollSavedState{"
|
||||||
|
+ Integer.toHexString(System.identityHashCode(this))
|
||||||
|
+ " scrollPosition=" + scrollOffsetFromStart
|
||||||
|
+ "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ScrollSavedState> CREATOR = new ClassLoaderCreator<ScrollSavedState>() {
|
||||||
|
public ScrollSavedState createFromParcel(Parcel in, ClassLoader loader)
|
||||||
|
{
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new ScrollSavedState(in, loader) : new ScrollSavedState(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScrollSavedState createFromParcel(Parcel in)
|
||||||
|
{
|
||||||
|
return createFromParcel(in, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScrollSavedState[] newArray(int size) {
|
||||||
|
return new ScrollSavedState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -21,6 +21,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewParent;
|
||||||
|
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
@ -512,6 +513,18 @@ public class Utils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if child is a descendant of parent, (or equal to the parent).
|
||||||
|
*/
|
||||||
|
static boolean isViewDescendantOf(View child, View parent) {
|
||||||
|
if (child == parent) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ViewParent childParent = child.getParent();
|
||||||
|
return (childParent instanceof ViewGroup) && isViewDescendantOf((View) childParent, parent);
|
||||||
|
}
|
||||||
|
|
||||||
// public static void clearBoxShadow(View view) {
|
// public static void clearBoxShadow(View view) {
|
||||||
// if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
|
// if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
|
||||||
// return;
|
// return;
|
||||||
|
@ -10,8 +10,6 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import androidx.core.widget.NestedScrollView;
|
import androidx.core.widget.NestedScrollView;
|
||||||
|
|
||||||
import org.nativescript.widgets.HorizontalScrollView.SavedState;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author hhristov
|
* @author hhristov
|
||||||
*/
|
*/
|
||||||
@ -22,7 +20,7 @@ public class VerticalScrollView extends NestedScrollView {
|
|||||||
private int contentMeasuredWidth = 0;
|
private int contentMeasuredWidth = 0;
|
||||||
private int contentMeasuredHeight = 0;
|
private int contentMeasuredHeight = 0;
|
||||||
private int scrollableLength = 0;
|
private int scrollableLength = 0;
|
||||||
private SavedState mSavedState;
|
private ScrollSavedState mSavedState;
|
||||||
private boolean isFirstLayout = true;
|
private boolean isFirstLayout = true;
|
||||||
private boolean scrollEnabled = true;
|
private boolean scrollEnabled = true;
|
||||||
|
|
||||||
@ -186,7 +184,7 @@ public class VerticalScrollView extends NestedScrollView {
|
|||||||
|
|
||||||
this.mIsLayoutDirty = false;
|
this.mIsLayoutDirty = false;
|
||||||
// Give a child focus if it needs it
|
// Give a child focus if it needs it
|
||||||
if (this.mChildToScrollTo != null && HorizontalScrollView.isViewDescendantOf(this.mChildToScrollTo, this)) {
|
if (this.mChildToScrollTo != null && Utils.isViewDescendantOf(this.mChildToScrollTo, this)) {
|
||||||
this.scrollToChild(this.mChildToScrollTo);
|
this.scrollToChild(this.mChildToScrollTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +198,7 @@ public class VerticalScrollView extends NestedScrollView {
|
|||||||
final int scrollRange = Math.max(0,
|
final int scrollRange = Math.max(0,
|
||||||
childHeight - (bottom - top - this.getPaddingTop() - this.getPaddingBottom()));
|
childHeight - (bottom - top - this.getPaddingTop() - this.getPaddingBottom()));
|
||||||
if (this.mSavedState != null) {
|
if (this.mSavedState != null) {
|
||||||
scrollY = mSavedState.scrollPosition;
|
scrollY = mSavedState.scrollOffsetFromStart;
|
||||||
mSavedState = null;
|
mSavedState = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +230,7 @@ public class VerticalScrollView extends NestedScrollView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onRestoreInstanceState(Parcelable state) {
|
protected void onRestoreInstanceState(Parcelable state) {
|
||||||
SavedState ss = (SavedState) state;
|
ScrollSavedState ss = (ScrollSavedState) state;
|
||||||
super.onRestoreInstanceState(ss.getSuperState());
|
super.onRestoreInstanceState(ss.getSuperState());
|
||||||
this.mSavedState = ss;
|
this.mSavedState = ss;
|
||||||
this.requestLayout();
|
this.requestLayout();
|
||||||
@ -241,8 +239,8 @@ public class VerticalScrollView extends NestedScrollView {
|
|||||||
@Override
|
@Override
|
||||||
protected Parcelable onSaveInstanceState() {
|
protected Parcelable onSaveInstanceState() {
|
||||||
Parcelable superState = super.onSaveInstanceState();
|
Parcelable superState = super.onSaveInstanceState();
|
||||||
SavedState ss = new SavedState(superState);
|
ScrollSavedState ss = new ScrollSavedState(superState);
|
||||||
ss.scrollPosition = this.getScrollY();
|
ss.scrollOffsetFromStart = this.getScrollY();
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user