Skip to content

Commit b7696bc

Browse files
committed
encodedCodes snap scrolling
1 parent 3904725 commit b7696bc

File tree

1 file changed

+108
-26
lines changed

1 file changed

+108
-26
lines changed

ui/src/main/java/io/snabble/sdk/ui/checkout/CheckoutEncodedCodesView.java

Lines changed: 108 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package io.snabble.sdk.ui.checkout;
22

3+
import android.annotation.SuppressLint;
34
import android.content.Context;
5+
import android.graphics.Rect;
46
import android.os.Handler;
57
import android.os.Looper;
68
import androidx.annotation.NonNull;
79
import android.util.DisplayMetrics;
10+
import android.view.MotionEvent;
811
import android.view.View;
912
import android.view.ViewGroup;
1013
import android.widget.Button;
@@ -29,6 +32,7 @@
2932
import io.snabble.sdk.ui.scanner.BarcodeView;
3033
import io.snabble.sdk.ui.telemetry.Telemetry;
3134
import io.snabble.sdk.ui.utils.OneShotClickListener;
35+
import io.snabble.sdk.utils.Logger;
3236

3337
class CheckoutEncodedCodesView extends FrameLayout implements View.OnLayoutChangeListener {
3438
private FrameLayout scrollContainer;
@@ -38,6 +42,9 @@ class CheckoutEncodedCodesView extends FrameLayout implements View.OnLayoutChang
3842
private CodeListView codeListView;
3943
private int maxSizeMm;
4044
private Button paidButton;
45+
private boolean isTouchReleased;
46+
private boolean isScrollingDown;
47+
private boolean handleScrollIdleState;
4148

4249
public CheckoutEncodedCodesView(Context context) {
4350
super(context);
@@ -78,17 +85,7 @@ public void click() {
7885

7986
Telemetry.event(Telemetry.Event.CheckoutFinishByUser);
8087
} else {
81-
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) codeListView.getLayoutManager();
82-
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) {
83-
@Override
84-
protected int getVerticalSnapPreference() {
85-
return SNAP_TO_START;
86-
}
87-
};
88-
89-
int scrollTo = getNextBarcodeIndex();
90-
smoothScroller.setTargetPosition(scrollTo);
91-
linearLayoutManager.startSmoothScroll(smoothScroller);
88+
scrollTo(getNextBarcodeIndex());
9289
}
9390
}
9491
});
@@ -109,23 +106,98 @@ protected int getVerticalSnapPreference() {
109106
}
110107

111108
public int getNextBarcodeIndex() {
112-
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) codeListView.getLayoutManager();
113-
if (linearLayoutManager != null) {
114-
return linearLayoutManager.findLastVisibleItemPosition();
109+
final LinearLayoutManager llm = (LinearLayoutManager) codeListView.getLayoutManager();
110+
if (llm != null) {
111+
return llm.findLastVisibleItemPosition();
115112
}
116113

117114
return 0;
118115
}
119116

120117
public boolean isAtLastBarcode() {
121-
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) codeListView.getLayoutManager();
122-
if (linearLayoutManager != null) {
123-
return linearLayoutManager.findLastCompletelyVisibleItemPosition() == linearLayoutManager.getItemCount() - 1;
118+
final LinearLayoutManager llm = (LinearLayoutManager) codeListView.getLayoutManager();
119+
if (llm != null) {
120+
return llm.findLastCompletelyVisibleItemPosition() == llm.getItemCount() - 1;
124121
}
125122

126123
return true;
127124
}
128125

126+
private void scrollTo(int position) {
127+
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) codeListView.getLayoutManager();
128+
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) {
129+
@Override
130+
protected int getVerticalSnapPreference() {
131+
return SNAP_TO_START;
132+
}
133+
};
134+
135+
smoothScroller.setTargetPosition(position);
136+
linearLayoutManager.startSmoothScroll(smoothScroller);
137+
}
138+
139+
private void handleTouchUp() {
140+
isTouchReleased = true;
141+
142+
if (handleScrollIdleState) {
143+
handleScrollIdleState = false;
144+
handleScrollIdleState();
145+
}
146+
}
147+
148+
private void handleScroll(int dy) {
149+
isScrollingDown = dy > 0;
150+
151+
CodeListViewAdapter adapter = ((CodeListViewAdapter)codeListView.getAdapter());
152+
153+
if (isAtLastBarcode()) {
154+
paidButton.setText(R.string.Snabble_QRCode_didPay);
155+
} else {
156+
paidButton.setText(getResources().getString(R.string.Snabble_QRCode_nextCode,
157+
getNextBarcodeIndex() + 1, adapter.getItemCount()));
158+
}
159+
}
160+
161+
private void handleScrollStateChanged(int newState) {
162+
if (newState == RecyclerView.SCROLL_STATE_SETTLING && isTouchReleased) {
163+
isTouchReleased = false;
164+
165+
final LinearLayoutManager llm = (LinearLayoutManager) codeListView.getLayoutManager();
166+
if (llm != null) {
167+
int currentPosition = llm.findFirstVisibleItemPosition();
168+
169+
if (isScrollingDown) {
170+
scrollTo(currentPosition + 1);
171+
} else {
172+
scrollTo(currentPosition);
173+
}
174+
}
175+
} else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
176+
if (isTouchReleased) {
177+
handleScrollIdleState();
178+
isTouchReleased = false;
179+
} else {
180+
handleScrollIdleState = true;
181+
}
182+
}
183+
}
184+
185+
private void handleScrollIdleState() {
186+
final LinearLayoutManager llm = (LinearLayoutManager) codeListView.getLayoutManager();
187+
if (llm != null) {
188+
int currentPosition = llm.findFirstVisibleItemPosition();
189+
View view = llm.findViewByPosition(currentPosition);
190+
191+
Rect r = new Rect();
192+
view.getGlobalVisibleRect(r);
193+
if (r.height() < view.getHeight() / 2) {
194+
scrollTo(currentPosition + 1);
195+
} else {
196+
scrollTo(currentPosition);
197+
}
198+
}
199+
}
200+
129201
@Override
130202
protected void onAttachedToWindow() {
131203
super.onAttachedToWindow();
@@ -148,6 +220,7 @@ public void onLayoutChange(View v, int left, int top, int right, int bottom,
148220
// this avoids a bug in <= API 16 where added views while layouting were discarded
149221
Handler handler = new Handler(Looper.getMainLooper());
150222
handler.post(new Runnable() {
223+
@SuppressLint("ClickableViewAccessibility")
151224
@Override
152225
public void run() {
153226
DisplayMetrics dm = getResources().getDisplayMetrics();
@@ -160,18 +233,27 @@ public void run() {
160233
scrollContainer.removeAllViews();
161234
codeListView = new CodeListView(getContext());
162235
scrollContainer.addView(codeListView, lp);
236+
237+
codeListView.setOnTouchListener(new OnTouchListener() {
238+
@Override
239+
public boolean onTouch(View v, MotionEvent event) {
240+
if (event.getAction() == MotionEvent.ACTION_UP) {
241+
handleTouchUp();
242+
}
243+
244+
return false;
245+
}
246+
});
247+
163248
codeListView.addOnScrollListener(new RecyclerView.OnScrollListener() {
249+
@Override
250+
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
251+
handleScrollStateChanged(newState);
252+
}
253+
164254
@Override
165255
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
166-
super.onScrolled(recyclerView, dx, dy);
167-
168-
CodeListViewAdapter adapter = ((CodeListViewAdapter)codeListView.getAdapter());
169-
if (isAtLastBarcode()) {
170-
paidButton.setText(R.string.Snabble_QRCode_didPay);
171-
} else {
172-
paidButton.setText(getResources().getString(R.string.Snabble_QRCode_nextCode,
173-
getNextBarcodeIndex() + 1, adapter.getItemCount()));
174-
}
256+
handleScroll(dy);
175257
}
176258
});
177259

0 commit comments

Comments
 (0)