Skip to content

Commit 54519ca

Browse files
committed
fix(android): prevent views from disappearing when using peaking
1 parent 5bfaec1 commit 54519ca

File tree

5 files changed

+154
-60
lines changed

5 files changed

+154
-60
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.nativescript.pager;
2+
3+
import androidx.recyclerview.widget.RecyclerView;
4+
import androidx.viewpager2.widget.ViewPager2;
5+
6+
import android.view.View;
7+
import android.view.ViewParent;
8+
9+
public final class PeakingTransformer implements ViewPager2.PageTransformer {
10+
/**
11+
* Creates a {@link PeakingTransformer}.
12+
*
13+
*/
14+
public PeakingTransformer() {
15+
}
16+
@Override
17+
public void transformPage(View page, float position) {
18+
ViewPager2 viewPager = requireViewPager(page);
19+
float offset = 0.0005f * position;
20+
boolean isRtl = viewPager.getLayoutDirection() == 1;
21+
if (viewPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) {
22+
page.setTranslationX(isRtl ? -offset : offset);
23+
} else {
24+
page.setTranslationY(offset);
25+
}
26+
}
27+
private ViewPager2 requireViewPager(View page) {
28+
ViewParent parent = page.getParent();
29+
ViewParent parentParent = parent.getParent();
30+
if (parent instanceof RecyclerView && parentParent instanceof ViewPager2) {
31+
return (ViewPager2) parentParent;
32+
}
33+
throw new IllegalStateException(
34+
"Expected the page view to be managed by a ViewPager2 instance.");
35+
}
36+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.nativescript.pager;
2+
import org.json.JSONObject;
3+
import org.json.JSONArray;
4+
public class Utils {
5+
public static void updateCollection(String update, androidx.recyclerview.widget.RecyclerView.Adapter< androidx.recyclerview.widget.RecyclerView.ViewHolder> adapter){
6+
try{
7+
JSONObject json = new JSONObject(update);
8+
int index = json.getInt("index");
9+
int addedCount;
10+
int removedCount;
11+
switch(json.getString("action")){
12+
case "add":
13+
addedCount = json.getInt("addedCount");
14+
adapter.notifyItemRangeInserted(
15+
index,
16+
addedCount
17+
);
18+
break;
19+
case "delete":
20+
removedCount = json.getInt("removedCount");
21+
adapter.notifyItemRangeRemoved(
22+
index,
23+
removedCount
24+
);
25+
break;
26+
case "update":
27+
adapter.notifyItemChanged(index);
28+
break;
29+
case "splice":
30+
removedCount = json.getInt("removedCount");
31+
addedCount = json.getInt("addedCount");
32+
if (removedCount > 0) {
33+
adapter.notifyItemRangeRemoved(
34+
index,
35+
removedCount
36+
);
37+
}
38+
if (addedCount > 0) {
39+
adapter.notifyItemRangeInserted(
40+
index,
41+
addedCount
42+
);
43+
}
44+
break;
45+
case "change":
46+
break;
47+
default:
48+
break;
49+
}
50+
}catch(Exception e){}
51+
}
52+
}

src/ui-pager/index.android.ts

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,14 @@ import {
1919
export * from './index.common';
2020
export { ItemsSource, Transformer } from './index.common';
2121

22-
function notifyForItemAtIndex(owner, nativeView: any, view: any, eventName: string, index: number) {
23-
const args = {
24-
eventName,
25-
object: owner,
26-
index,
27-
view,
28-
ios: undefined,
29-
android: nativeView
30-
};
31-
owner.notify(args);
32-
return args;
33-
}
34-
3522
const PLACEHOLDER = 'PLACEHOLDER';
23+
const sdkVersion = parseInt(Device.sdkVersion, 10);
24+
25+
export const pagesCountProperty = new Property<Pager, number>({
26+
name: 'pagesCount',
27+
defaultValue: -1,
28+
valueConverter: parseInt
29+
});
3630

3731
export class Pager extends PagerBase {
3832
nativeViewProtected: androidx.viewpager2.widget.ViewPager2;
@@ -59,6 +53,7 @@ export class Pager extends PagerBase {
5953
private _lastPeaking = 0;
6054
private compositeTransformer: androidx.viewpager2.widget.CompositePageTransformer;
6155
private marginTransformer: androidx.viewpager2.widget.MarginPageTransformer;
56+
private peakingTransformer: com.nativescript.pager.PeakingTransformer;
6257
private _transformers: androidx.viewpager2.widget.ViewPager2.PageTransformer[];
6358

6459
constructor() {
@@ -74,10 +69,9 @@ export class Pager extends PagerBase {
7469
this._views = value;
7570
}
7671

77-
@profile()
7872
public createNativeView() {
7973
const nativeView = new androidx.viewpager2.widget.ViewPager2(this._context);
80-
const sdkVersion = parseInt(Device.sdkVersion, 10);
74+
nativeView.setOffscreenPageLimit(-1);
8175
if (sdkVersion >= 21) {
8276
nativeView.setNestedScrollingEnabled(true);
8377
}
@@ -87,23 +81,24 @@ export class Pager extends PagerBase {
8781
nativeView.setOrientation(androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL);
8882
}
8983

90-
initPagerRecyclerAdapter();
91-
this._pagerAdapter = new PagerRecyclerAdapter(new WeakRef(this));
92-
this.compositeTransformer = new androidx.viewpager2.widget.CompositePageTransformer();
93-
nativeView.setUserInputEnabled(!this.disableSwipe);
94-
this.on(View.layoutChangedEvent, this.onLayoutChange, this);
9584
return nativeView;
9685
}
9786

9887
public initNativeView() {
9988
super.initNativeView();
89+
const nativeView = this.nativeViewProtected;
90+
initPagerRecyclerAdapter();
91+
this._pagerAdapter = new PagerRecyclerAdapter(new WeakRef(this));
92+
this.compositeTransformer = new androidx.viewpager2.widget.CompositePageTransformer();
93+
nativeView.setPageTransformer(this.compositeTransformer);
94+
nativeView.setUserInputEnabled(!this.disableSwipe);
95+
this.on(View.layoutChangedEvent, this.onLayoutChange, this);
10096
// Store disable animation value
10197
this._oldDisableAnimation = this.disableAnimation;
10298
// Disable animation to set currentItem w/o animation
10399
this.disableAnimation = true;
104100
initPagerChangeCallback();
105101
this._pageListener = new PageChangeCallback(new WeakRef(this));
106-
const nativeView = this.nativeViewProtected;
107102
nativeView.registerOnPageChangeCallback(this._pageListener);
108103
nativeView.setAdapter(this._pagerAdapter);
109104
if (this._androidViewId < 0) {
@@ -116,8 +111,6 @@ export class Pager extends PagerBase {
116111
nativeView.setOffscreenPageLimit(3);
117112
}
118113

119-
this._setPeaking(this.peaking);
120-
this._setSpacing(this.spacing);
121114
this._setTransformers(this.transformers ? this.transformers : '');
122115
}
123116

@@ -160,50 +153,58 @@ export class Pager extends PagerBase {
160153
this.initStaticPagerAdapter();
161154
}
162155
onLayoutChange(args: any) {
163-
this._setSpacing(args.object.spacing);
164-
this._setPeaking(args.object.peaking);
165-
this._setTransformers(this.transformers ? this.transformers : '');
156+
if (this._lastPeaking) {
157+
this[peakingProperty.setNative](this.peaking);
158+
}
159+
if (this._lastSpacing) {
160+
this[spacingProperty.setNative](this.spacing);
161+
}
162+
// this._setTransformers(this.transformers ? this.transformers : '');
166163
this._updateScrollPosition();
167164
// Set disableAnimation to original value
168165
this.disableAnimation = this._oldDisableAnimation;
169166
}
170167

171-
private _setSpacing(value: any) {
168+
[spacingProperty.setNative](value: any) {
169+
console.log('spacingProperty', value);
172170
const size = this.convertToSize(value);
173171
const newSpacing = size !== this._lastSpacing;
174172
if (newSpacing) {
175173
if (this.marginTransformer) {
176174
this.compositeTransformer.removeTransformer(this.marginTransformer);
175+
this.marginTransformer = null;
176+
}
177+
if (size !== 0) {
178+
this.marginTransformer = new androidx.viewpager2.widget.MarginPageTransformer(size);
179+
this.compositeTransformer.addTransformer(this.marginTransformer);
180+
if (this.peakingTransformer) {
181+
this.compositeTransformer.removeTransformer(this.peakingTransformer);
182+
this.peakingTransformer = null;
183+
}
177184
}
178-
179-
this.marginTransformer = new androidx.viewpager2.widget.MarginPageTransformer(size);
180-
this.compositeTransformer.addTransformer(this.marginTransformer);
181185
this._lastSpacing = size;
182186
}
183187
}
184188

185-
private _setPeaking(value: any) {
189+
[peakingProperty.setNative](value: any) {
186190
const size = this.convertToSize(value);
187191
const newPeaking = size !== this._lastPeaking;
188192
if (newPeaking) {
189193
const nativeView = this.nativeViewProtected;
190-
nativeView.setClipToPadding(false);
191194
const left = this.orientation === 'horizontal' ? size : 0;
192195
const top = this.orientation === 'horizontal' ? 0 : size;
196+
const enabled = left !== 0 || top !== 0;
193197
nativeView.setPadding(left, top, left, top);
194-
nativeView.setClipChildren(false);
198+
nativeView.setClipChildren(!enabled);
199+
nativeView.setClipToPadding(!enabled);
200+
if (!this.peakingTransformer && !this.marginTransformer) {
201+
this.peakingTransformer = new com.nativescript.pager.PeakingTransformer();
202+
this.compositeTransformer.addTransformer(this.peakingTransformer);
203+
}
195204
this._lastPeaking = size;
196205
}
197206
}
198207

199-
[spacingProperty.setNative](value: any) {
200-
this._setSpacing(value);
201-
}
202-
203-
[peakingProperty.setNative](value: any) {
204-
this._setPeaking(value);
205-
}
206-
207208
private _setTransformers(transformers: string) {
208209
if (!isString(transformers)) {
209210
return;
@@ -212,6 +213,7 @@ export class Pager extends PagerBase {
212213
this._transformers.forEach((transformer) => {
213214
this.compositeTransformer.removeTransformer(transformer);
214215
});
216+
console.log('_setTransformers', transformers);
215217
for (const transformer of transformsArray) {
216218
const nativeTransformerClass = Pager.mRegisteredTransformers[transformer];
217219
if (nativeTransformerClass) {
@@ -389,14 +391,6 @@ export class Pager extends PagerBase {
389391
}
390392
}
391393

392-
updatePagesCount(value: number) {
393-
const nativeView = this.nativeViewProtected;
394-
if (nativeView) {
395-
this._pagerAdapter.notifyDataSetChanged();
396-
nativeView.setOffscreenPageLimit(value);
397-
}
398-
}
399-
400394
onUnloaded() {
401395
// this._android.setAdapter(null);
402396
super.onUnloaded();
@@ -471,6 +465,13 @@ export class Pager extends PagerBase {
471465
this._initAutoPlay(this.autoPlay);
472466
}
473467
}
468+
[pagesCountProperty.setNative](value: number) {
469+
const nativeView = this.nativeViewProtected;
470+
if (nativeView && (value === -1 || value > 0)) {
471+
this._pagerAdapter.notifyDataSetChanged();
472+
nativeView.setOffscreenPageLimit(value);
473+
}
474+
}
474475

475476
_nextIndex(): number {
476477
const next = this.selectedIndex + 1;
@@ -558,14 +559,6 @@ export class Pager extends PagerBase {
558559
}
559560
}
560561

561-
export const pagesCountProperty = new Property<Pager, number>({
562-
name: 'pagesCount',
563-
defaultValue: 0,
564-
valueConverter: (v) => parseInt(v, 10),
565-
valueChanged: (pager: Pager, oldValue, newValue) => {
566-
pager.updatePagesCount(pager.pagesCount);
567-
}
568-
});
569562
pagesCountProperty.register(Pager);
570563

571564
let PageChangeCallback;

src/ui-pager/index.common.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,13 @@ export abstract class PagerBase extends ContainerView implements AddChildFromBui
322322
converted = size * length.value;
323323
} else if (typeof length === 'string') {
324324
if (length.indexOf('px') > -1) {
325-
converted = parseInt(length.replace('px', ''), 10);
325+
converted = parseFloat(length.replace('px', ''));
326326
} else if (length.indexOf('dip') > -1) {
327327
converted = Utils.layout.toDevicePixels(parseInt(length.replace('dip', ''), 10));
328328
} else if (length.indexOf('%') > -1) {
329-
converted = size * (parseInt(length.replace('%', ''), 10) / 100);
329+
converted = size * (parseFloat(length.replace('%', '')) / 100);
330330
} else {
331-
converted = Utils.layout.toDevicePixels(parseInt(length, 10));
331+
converted = Utils.layout.toDevicePixels(parseFloat(length));
332332
}
333333
} else if (typeof length === 'number') {
334334
converted = Utils.layout.toDevicePixels(length);

src/ui-pager/typings/android.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
declare namespace com {
2+
export namespace nativescript {
3+
export namespace pager {
4+
export class PeakingTransformer extends ViewPager2.PageTransformer {
5+
public static class: java.lang.Class<PeakingTransformer>;
6+
7+
public transformPage(param0: globalAndroid.view.View, param1: number): void;
8+
9+
public constructor();
10+
}
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)