fix(android): ScrollView BadParcelableException (#10213)

This commit is contained in:
Dimitris-Rafail Katsampas
2023-02-17 16:03:43 +02:00
committed by GitHub
parent 0183f7e643
commit a26a03eeb8
6 changed files with 91 additions and 75 deletions

View File

@ -223,8 +223,9 @@ public class GridLayout extends LayoutBase {
}
private void removeFromMap(View child) {
this.map.get(child).child = null;
this.map.remove(child);
if (this.map.containsKey(child)) {
this.map.remove(child).child = null;
}
}
@Override

View File

@ -2,17 +2,13 @@ package org.nativescript.widgets;
import android.content.Context;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
/**
* @author hhristov
*/
@ -23,7 +19,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
private int contentMeasuredWidth = 0;
private int contentMeasuredHeight = 0;
private int scrollableLength = 0;
private SavedState mSavedState;
private ScrollSavedState mSavedState;
private boolean isFirstLayout = true;
private boolean scrollEnabled = true;
@ -180,7 +176,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
this.mIsLayoutDirty = false;
// 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);
}
@ -194,7 +190,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
final int scrollRange = Math.max(0, childWidth - (right - left - this.getPaddingLeft() - this.getPaddingRight()));
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;
} else {
if (this.isLayoutRtl()) {
@ -228,7 +224,7 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
ScrollSavedState ss = (ScrollSavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
this.mSavedState = ss;
this.requestLayout();
@ -237,9 +233,8 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.scrollPosition = this.getScrollX();
ss.isLayoutRtl = this.isLayoutRtl();
ScrollSavedState ss = new ScrollSavedState(superState);
ss.scrollOffsetFromStart = isLayoutRtl() ? -this.getScrollX() : this.getScrollX();
return ss;
}
@ -258,58 +253,4 @@ public class HorizontalScrollView extends android.widget.HorizontalScrollView {
private boolean isLayoutRtl() {
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];
}
};
}
}

View File

@ -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];
}
};
}

View File

@ -21,6 +21,7 @@ import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import androidx.appcompat.content.res.AppCompatResources;
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) {
// if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
// return;

View File

@ -10,8 +10,6 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.core.widget.NestedScrollView;
import org.nativescript.widgets.HorizontalScrollView.SavedState;
/**
* @author hhristov
*/
@ -22,7 +20,7 @@ public class VerticalScrollView extends NestedScrollView {
private int contentMeasuredWidth = 0;
private int contentMeasuredHeight = 0;
private int scrollableLength = 0;
private SavedState mSavedState;
private ScrollSavedState mSavedState;
private boolean isFirstLayout = true;
private boolean scrollEnabled = true;
@ -186,7 +184,7 @@ public class VerticalScrollView extends NestedScrollView {
this.mIsLayoutDirty = false;
// 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);
}
@ -200,7 +198,7 @@ public class VerticalScrollView extends NestedScrollView {
final int scrollRange = Math.max(0,
childHeight - (bottom - top - this.getPaddingTop() - this.getPaddingBottom()));
if (this.mSavedState != null) {
scrollY = mSavedState.scrollPosition;
scrollY = mSavedState.scrollOffsetFromStart;
mSavedState = null;
}
@ -232,7 +230,7 @@ public class VerticalScrollView extends NestedScrollView {
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
ScrollSavedState ss = (ScrollSavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
this.mSavedState = ss;
this.requestLayout();
@ -241,8 +239,8 @@ public class VerticalScrollView extends NestedScrollView {
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
ss.scrollPosition = this.getScrollY();
ScrollSavedState ss = new ScrollSavedState(superState);
ss.scrollOffsetFromStart = this.getScrollY();
return ss;
}