mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-19 06:10:56 +08:00
Merge branch 'nestedscrollview' of github.com:Akylas/NativeScript
This commit is contained in:
@ -9,6 +9,7 @@ export class ScrollView extends ScrollViewBase {
|
|||||||
nativeViewProtected: org.nativescript.widgets.VerticalScrollView | org.nativescript.widgets.HorizontalScrollView;
|
nativeViewProtected: org.nativescript.widgets.VerticalScrollView | org.nativescript.widgets.HorizontalScrollView;
|
||||||
private _androidViewId = -1;
|
private _androidViewId = -1;
|
||||||
private handler: android.view.ViewTreeObserver.OnScrollChangedListener;
|
private handler: android.view.ViewTreeObserver.OnScrollChangedListener;
|
||||||
|
private scrollChangeHandler: androidx.core.widget.NestedScrollView.OnScrollChangeListener;
|
||||||
|
|
||||||
get horizontalOffset(): number {
|
get horizontalOffset(): number {
|
||||||
const nativeView = this.nativeViewProtected;
|
const nativeView = this.nativeViewProtected;
|
||||||
@ -99,7 +100,13 @@ export class ScrollView extends ScrollViewBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createNativeView() {
|
public createNativeView() {
|
||||||
return this.orientation === 'horizontal' ? new org.nativescript.widgets.HorizontalScrollView(this._context) : new org.nativescript.widgets.VerticalScrollView(this._context);
|
if (this.orientation === 'horizontal') {
|
||||||
|
return new org.nativescript.widgets.HorizontalScrollView(this._context);
|
||||||
|
} else {
|
||||||
|
const view = new org.nativescript.widgets.VerticalScrollView(this._context);
|
||||||
|
view.setVerticalScrollBarEnabled(true);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public initNativeView(): void {
|
public initNativeView(): void {
|
||||||
@ -123,6 +130,22 @@ export class ScrollView extends ScrollViewBase {
|
|||||||
|
|
||||||
protected attachNative() {
|
protected attachNative() {
|
||||||
const that = new WeakRef(this);
|
const that = new WeakRef(this);
|
||||||
|
if (this.orientation === 'vertical') {
|
||||||
|
this.scrollChangeHandler = new androidx.core.widget.NestedScrollView.OnScrollChangeListener({
|
||||||
|
onScrollChange(view, scrollX, scrollY) {
|
||||||
|
const owner: ScrollView = that.get();
|
||||||
|
if (owner) {
|
||||||
|
owner.notify({
|
||||||
|
object: owner,
|
||||||
|
eventName: ScrollView.scrollEvent,
|
||||||
|
scrollX: layout.toDeviceIndependentPixels(scrollX),
|
||||||
|
scrollY: layout.toDeviceIndependentPixels(scrollY)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.nativeView.setOnScrollChangeListener(this.scrollChangeHandler);
|
||||||
|
} else {
|
||||||
this.handler = new android.view.ViewTreeObserver.OnScrollChangedListener({
|
this.handler = new android.view.ViewTreeObserver.OnScrollChangedListener({
|
||||||
onScrollChanged: function () {
|
onScrollChanged: function () {
|
||||||
const owner: ScrollView = that.get();
|
const owner: ScrollView = that.get();
|
||||||
@ -131,9 +154,9 @@ export class ScrollView extends ScrollViewBase {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
this.nativeViewProtected.getViewTreeObserver().addOnScrollChangedListener(this.handler);
|
this.nativeViewProtected.getViewTreeObserver().addOnScrollChangedListener(this.handler);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _lastScrollX = -1;
|
private _lastScrollX = -1;
|
||||||
private _lastScrollY = -1;
|
private _lastScrollY = -1;
|
||||||
@ -158,9 +181,15 @@ export class ScrollView extends ScrollViewBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected dettachNative() {
|
protected dettachNative() {
|
||||||
|
if (this.handler) {
|
||||||
this.nativeViewProtected.getViewTreeObserver().removeOnScrollChangedListener(this.handler);
|
this.nativeViewProtected.getViewTreeObserver().removeOnScrollChangedListener(this.handler);
|
||||||
this.handler = null;
|
this.handler = null;
|
||||||
}
|
}
|
||||||
|
if (this.scrollChangeHandler) {
|
||||||
|
this.nativeView.setOnScrollChangeListener(null);
|
||||||
|
this.scrollChangeHandler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScrollView.prototype.recycleNativeView = 'never';
|
ScrollView.prototype.recycleNativeView = 'never';
|
||||||
|
@ -359,7 +359,7 @@
|
|||||||
constructor(context: android.content.Context);
|
constructor(context: android.content.Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VerticalScrollView extends android.widget.ScrollView {
|
export class VerticalScrollView extends androidx.core.widget.NestedScrollView {
|
||||||
constructor(context: android.content.Context);
|
constructor(context: android.content.Context);
|
||||||
public getScrollableLength(): number;
|
public getScrollableLength(): number;
|
||||||
public getScrollEnabled(): boolean;
|
public getScrollEnabled(): boolean;
|
||||||
|
@ -12,13 +12,13 @@ import android.view.MotionEvent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ScrollView;
|
import androidx.core.widget.NestedScrollView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author hhristov
|
* @author hhristov
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class VerticalScrollView extends ScrollView {
|
public class VerticalScrollView extends NestedScrollView {
|
||||||
|
|
||||||
private final Rect mTempRect = new Rect();
|
private final Rect mTempRect = new Rect();
|
||||||
|
|
||||||
@ -36,9 +36,9 @@ public class VerticalScrollView extends ScrollView {
|
|||||||
private boolean mIsLayoutDirty = true;
|
private boolean mIsLayoutDirty = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The child to give focus to in the event that a child has requested focus while the
|
* The child to give focus to in the event that a child has requested focus
|
||||||
* layout is dirty. This prevents the scroll from being wrong if the child has not been
|
* while the layout is dirty. This prevents the scroll from being wrong if the
|
||||||
* laid out before requesting focus.
|
* child has not been laid out before requesting focus.
|
||||||
*/
|
*/
|
||||||
private View mChildToScrollTo = null;
|
private View mChildToScrollTo = null;
|
||||||
|
|
||||||
@ -70,7 +70,8 @@ public class VerticalScrollView extends ScrollView {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent ev) {
|
public boolean onTouchEvent(MotionEvent ev) {
|
||||||
if (!this.scrollEnabled && (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE)) {
|
if (!this.scrollEnabled
|
||||||
|
&& (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,8 +123,7 @@ public class VerticalScrollView extends ScrollView {
|
|||||||
public void requestChildFocus(View child, View focused) {
|
public void requestChildFocus(View child, View focused) {
|
||||||
if (!this.mIsLayoutDirty) {
|
if (!this.mIsLayoutDirty) {
|
||||||
this.scrollToChild(focused);
|
this.scrollToChild(focused);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// The child may not be laid out yet, we can't compute the scroll yet
|
// The child may not be laid out yet, we can't compute the scroll yet
|
||||||
this.mChildToScrollTo = focused;
|
this.mChildToScrollTo = focused;
|
||||||
}
|
}
|
||||||
@ -135,26 +135,30 @@ public class VerticalScrollView extends ScrollView {
|
|||||||
CommonLayoutParams.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
CommonLayoutParams.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
|
||||||
|
|
||||||
// Don't call measure because it will measure content twice.
|
// Don't call measure because it will measure content twice.
|
||||||
// ScrollView is expected to have single child so we measure only the first child.
|
// ScrollView is expected to have single child so we measure only the first
|
||||||
|
// child.
|
||||||
View child = this.getChildCount() > 0 ? this.getChildAt(0) : null;
|
View child = this.getChildCount() > 0 ? this.getChildAt(0) : null;
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
this.scrollableLength = 0;
|
this.scrollableLength = 0;
|
||||||
this.contentMeasuredWidth = 0;
|
this.contentMeasuredWidth = 0;
|
||||||
this.contentMeasuredHeight = 0;
|
this.contentMeasuredHeight = 0;
|
||||||
this.setPadding(0, 0, 0, 0);
|
this.setPadding(0, 0, 0, 0);
|
||||||
}
|
} else {
|
||||||
else {
|
CommonLayoutParams.measureChild(child, widthMeasureSpec,
|
||||||
CommonLayoutParams.measureChild(child, widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
|
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
|
||||||
this.contentMeasuredWidth = CommonLayoutParams.getDesiredWidth(child);
|
this.contentMeasuredWidth = CommonLayoutParams.getDesiredWidth(child);
|
||||||
this.contentMeasuredHeight = CommonLayoutParams.getDesiredHeight(child);
|
this.contentMeasuredHeight = CommonLayoutParams.getDesiredHeight(child);
|
||||||
|
|
||||||
// Android ScrollView does not account to child margins so we set them as paddings. Otherwise you can never scroll to bottom.
|
// Android ScrollView does not account to child margins so we set them as
|
||||||
|
// paddings. Otherwise you can never scroll to bottom.
|
||||||
CommonLayoutParams lp = (CommonLayoutParams) child.getLayoutParams();
|
CommonLayoutParams lp = (CommonLayoutParams) child.getLayoutParams();
|
||||||
this.setPadding(lp.leftMargin, lp.topMargin, lp.rightMargin, lp.bottomMargin);
|
this.setPadding(lp.leftMargin, lp.topMargin, lp.rightMargin, lp.bottomMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't add in our paddings because they are already added as child margins. (we will include them twice if we add them).
|
// Don't add in our paddings because they are already added as child margins.
|
||||||
// check the previous line - this.setPadding(lp.leftMargin, lp.topMargin, lp.rightMargin, lp.bottomMargin);
|
// (we will include them twice if we add them).
|
||||||
|
// check the previous line - this.setPadding(lp.leftMargin, lp.topMargin,
|
||||||
|
// lp.rightMargin, lp.bottomMargin);
|
||||||
// this.contentMeasuredWidth += this.getPaddingLeft() + this.getPaddingRight();
|
// this.contentMeasuredWidth += this.getPaddingLeft() + this.getPaddingRight();
|
||||||
// this.contentMeasuredHeight += this.getPaddingTop() + this.getPaddingBottom();
|
// this.contentMeasuredHeight += this.getPaddingTop() + this.getPaddingBottom();
|
||||||
|
|
||||||
@ -196,7 +200,8 @@ public class VerticalScrollView extends ScrollView {
|
|||||||
if (this.isFirstLayout) {
|
if (this.isFirstLayout) {
|
||||||
this.isFirstLayout = false;
|
this.isFirstLayout = false;
|
||||||
|
|
||||||
final int scrollRange = Math.max(0, childHeight - (bottom - top - this.getPaddingTop() - this.getPaddingBottom()));
|
final int scrollRange = Math.max(0,
|
||||||
|
childHeight - (bottom - top - this.getPaddingTop() - this.getPaddingBottom()));
|
||||||
if (this.mSavedState != null) {
|
if (this.mSavedState != null) {
|
||||||
scrollY = mSavedState.scrollPosition;
|
scrollY = mSavedState.scrollPosition;
|
||||||
mSavedState = null;
|
mSavedState = null;
|
||||||
@ -217,13 +222,13 @@ public class VerticalScrollView extends ScrollView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
public void onAttachedToWindow() {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
this.isFirstLayout = true;
|
this.isFirstLayout = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
public void onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
this.isFirstLayout = true;
|
this.isFirstLayout = true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user