Skip to content

Commit 6ed9ad0

Browse files
committed
fixed inner view click,add next view form top
1 parent d2b50a6 commit 6ed9ad0

2 files changed

Lines changed: 130 additions & 94 deletions

File tree

stacklayout/src/main/java/com/uis/stackview/StackHelper.java

Lines changed: 116 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import android.os.Looper;
77
import android.util.Log;
88
import android.view.View;
9-
import android.view.animation.AccelerateInterpolator;
109
import android.view.animation.DecelerateInterpolator;
1110
import android.view.animation.Interpolator;
1211
import android.view.animation.LinearInterpolator;
@@ -28,11 +27,13 @@
2827

2928
final class StackHelper implements ValueAnimator.AnimatorUpdateListener{
3029

31-
private static long clickMills = System.currentTimeMillis();
30+
private long clickMills = System.currentTimeMillis();
3231
private ScheduledThreadPoolExecutor executor;
3332
/** 判定为滑动的阈值,单位是像素 */
3433
private final int mTouchSlop;
3534
private int swipModel = MODEL_NONE;
35+
/** true:顶层将移除,false:顶层将加新*/
36+
private boolean isTopRemove;
3637
private LinkedList<WeakReference<View>> weakViews = new LinkedList<>();
3738
private List<Integer> originX = new ArrayList<>();
3839
private ReleaseAnimator mAnimator = new ReleaseAnimator();
@@ -44,26 +45,25 @@ final class StackHelper implements ValueAnimator.AnimatorUpdateListener{
4445
private boolean enableScroll = false;
4546
private int displayPosition = 0;
4647
private StackLayout layout;
48+
private boolean debug = false;
4749

4850
StackHelper(int touchSlop) {
4951
mTouchSlop = touchSlop;
5052
}
5153

5254
void bindLayout(StackLayout layout) {
53-
//log("bindLayout...");
5455
if(this.layout == null) {
5556
this.layout = layout;
5657
}
5758
setAutoPlay(this.layout.stackLooper);
5859
}
5960

6061
void unbindLayout() {
61-
//log("unbindLayout...");
6262
setAutoPlay(false);
6363
}
6464

6565
void measureChild(int width,int height){
66-
log("measue...");
66+
//log("measue...");
6767
if(layout != null && layout.getAdapter() != null && layout.getAdapter().getItemCount() > 0 ){
6868
int size = layout.getRealStackSize();
6969
if(originX.isEmpty()) {
@@ -93,33 +93,48 @@ void measureChild(int width,int height){
9393
}
9494

9595
void layoutChild(){
96-
log("layout..."+layout.getChildCount());
96+
//log("layout..."+layout.getChildCount());
9797
if(needRelayout && layout != null) {
9898
needRelayout = false;
99-
//log("childCount="+layout.getChildCount());
100-
for (int i = 0, size = layout.getChildCount(); i < size && i < layout.stackSize; i++) {
99+
int childSize = layout.getChildCount();
100+
int stackSize = layout.stackSize;
101+
for (int i = 0; i < childSize; i++) {
102+
int top, bottom, left, right, pivot;
101103
View view = layout.getChildAt(i);
102-
int x = originX.get(i);
103-
int top,bottom,left, right, pivot;
104-
if (layout.stackEdgeModel == MODEL_LEFT) {
105-
left = x;
106-
right = everyWidth + x;
107-
pivot = layout.stackEdge;
108-
} else {
109-
right = layout.getWidth() - x;
110-
left = right - everyWidth;
111-
pivot = layout.getWidth() - layout.stackEdge;
112-
}
113104
top = layout.getPaddingTop();
114105
bottom = everyHeight + top;
115-
left += layout.getPaddingLeft();
116-
view.setPivotX(pivot);
117-
view.setPivotY(everyHeight / 2);
118-
view.layout(left, top, right, bottom);
119-
if (i < size - 1) {
120-
view.setScaleY(getChildScale(i,layout.stackZoomY));
121-
} else {
122-
view.setScaleY(1f);
106+
if(i < stackSize) {
107+
int x = originX.get(i);
108+
if (layout.stackEdgeModel == MODEL_LEFT) {
109+
left = x;
110+
right = everyWidth + left;
111+
pivot = layout.stackEdge;
112+
} else {
113+
right = layout.getWidth() - x;
114+
left = right - everyWidth;
115+
pivot = layout.getWidth() - layout.stackEdge;
116+
}
117+
view.setPivotX(pivot);
118+
view.setPivotY(everyHeight / 2);
119+
view.layout(left, top, right, bottom);
120+
view.setScaleY(getChildScale(i, layout.stackZoomY));
121+
if(view.getTranslationX() != 0f){
122+
if(i+1 < stackSize){
123+
view.setTranslationX(0);
124+
}else if(i+1 == stackSize && childSize == stackSize){//恢复stackSize时,补偿距离
125+
float distance = layout.stackEdgeModel == MODEL_RIGHT ? -everyWidth : everyWidth;
126+
view.setTranslationX(view.getTranslationX()+distance);
127+
}
128+
}
129+
}else if(!isTopRemove){//顶层加入
130+
if (layout.stackEdgeModel == MODEL_LEFT) {
131+
left = layout.getWidth() - layout.stackEdge;
132+
right = everyWidth + left;
133+
}else{
134+
right = layout.stackEdge;
135+
left = right - everyWidth;
136+
}
137+
view.layout(left, top, right, bottom);
123138
}
124139
}
125140
}
@@ -173,7 +188,8 @@ private void removeStackView(View view){
173188
if(view != null && layout != null) {
174189
layout.removeView(view);
175190
view.setTranslationX(0);
176-
weakViews.add(new WeakReference<View>(view));
191+
view.setScaleY(1f);
192+
weakViews.add(new WeakReference<>(view));
177193
}
178194
}
179195

@@ -212,16 +228,21 @@ void fingerTouchDown(){
212228
void executeScroll(int dx) {
213229
//dx<0 left, dx>0 right
214230
if(layout.getChildCount() > 0 && !mAnimator.isRunning()) {
231+
View view;
215232
//判断滑动方向
216-
if(swipModel == MODEL_NONE){
233+
if(MODEL_NONE == swipModel){
217234
swipModel = dx < 0 ? MODEL_LEFT : MODEL_RIGHT;
235+
isTopRemove = layout.stackEdgeModel != swipModel;
236+
if(isTopRemove){
237+
view = layout.getChildAt(layout.getChildCount()-1);
238+
}else{
239+
view = addTopView();
240+
}
241+
mAnimator.setAnimatorView(view);
242+
}else{
243+
view = mAnimator.mAnimatorView;
218244
}
219-
for (int size = layout.getChildCount(), i = size - 1; i < size; i++) {
220-
View itemView = layout.getChildAt(i);
221-
itemView.setTranslationX(itemView.getTranslationX() + 0.8f * dx);
222-
StackHelper.log("dx = " + dx + ",view transX = " + itemView.getTranslationX());
223-
mAnimator.setAnimatorView(itemView);
224-
}
245+
view.setTranslationX(view.getTranslationX() + 1.0f*everyWidth/layout.getWidth() * dx);
225246
}
226247
}
227248

@@ -232,39 +253,36 @@ void releaseScroll(int velocity){
232253
setAutoPlay(layout.stackLooper);
233254
float transX = mAnimator.getTranslationX();
234255
if(layout.getAdapter() != null && Math.abs(transX) > 0 && !mAnimator.isRunning()) {
235-
StackHelper.log("end = " + transX);
236256
//滑动速度大于限定或者滑动距离大于宽度一部分,移出当前视图可视范围
237-
boolean recover = true;
238257
if(Math.abs(velocity) >= everyWidth || Math.abs(transX) > mMaxDistance){
239-
if(MODEL_LEFT == swipModel){
240-
if(isRightMoveOutLeft()){
241-
addBottomView();
242-
recover = false;
243-
}else{
244-
addTopView();
245-
}
246-
}else if(MODEL_RIGHT == swipModel){
247-
if(isLeftMoveOutRight()){
248-
addBottomView();
249-
recover = false;
250-
}else{
251-
addTopView();
252-
}
258+
int sign = MODEL_LEFT == swipModel ? -1 : 1;
259+
if(isTopRemove){
260+
addBottomView();
261+
transX = layout.getWidth()*sign - transX;
262+
mAnimator.startAnimator(true,false,transX,mMaxDistance,this);
263+
}else{
264+
removeBottomView();
265+
transX = everyWidth*sign - transX;
266+
mAnimator.startAnimator(false,false,transX,mMaxDistance,this);
253267
}
254-
if(!recover) {
255-
transX = layout.getWidth() * Math.signum(transX) - transX;
256-
}
257-
}
258-
if(recover){//取反恢复原样
268+
}else {
269+
//取反恢复原样
259270
transX *= -1;
271+
mAnimator.startAnimator(!isTopRemove,false,transX,mMaxDistance,this);
260272
}
261-
StackHelper.log("velocity = " + velocity+",end = " + transX + ",distance="+mMaxDistance+ ",needRemoveTopView="+!recover +
262-
",recover=" + recover + ",swipModel =" + swipModel + ",edgeModel=" + layout.stackEdgeModel);
263-
mAnimator.startAnimator(!recover,false,transX,mMaxDistance,this);
264273
swipModel = MODEL_NONE;
265274
}
266275
}
267276

277+
void autoScroll(){
278+
if(layout.getChildCount() > 0 && !isFingerTouch && !mAnimator.isRunning()) {
279+
mAnimator.setAnimatorView(layout.getChildAt(layout.getChildCount() - 1));
280+
int transX = (layout.stackEdgeModel == MODEL_LEFT ? 1 : -1)*layout.getWidth();
281+
isTopRemove = true;
282+
mAnimator.startAnimator(true,true,transX,mMaxDistance,this);
283+
}
284+
}
285+
268286
void setAutoPlay(boolean looper){
269287
if(looper) {
270288
if(executor == null || executor.isShutdown()){
@@ -280,23 +298,7 @@ void setAutoPlay(boolean looper){
280298
}
281299
}
282300

283-
void autoScroll(){
284-
if(layout.getChildCount() > 0 && !isFingerTouch && !mAnimator.isRunning()) {
285-
mAnimator.setAnimatorView(layout.getChildAt(layout.getChildCount() - 1));
286-
int transX = (layout.stackEdgeModel == MODEL_LEFT ? 1 : -1)*layout.getWidth();
287-
mAnimator.startAnimator(true,true,transX,mMaxDistance,this);
288-
}
289-
}
290-
291-
private boolean isLeftMoveOutRight(){
292-
return layout.stackEdgeModel == MODEL_LEFT && swipModel == MODEL_RIGHT;
293-
}
294-
295-
private boolean isRightMoveOutLeft(){
296-
return layout.stackEdgeModel == MODEL_RIGHT && swipModel == MODEL_LEFT;
297-
}
298-
299-
/** 移除顶层 */
301+
/** 加入底层 */
300302
private void addBottomView(){
301303
int cnt = layout.getAdapter().getItemCount();
302304
displayPosition += 1;
@@ -310,8 +312,30 @@ private void addBottomView(){
310312
}
311313

312314
/** 加入顶层 */
313-
private void addTopView(){
315+
private View addTopView(){
316+
int cnt = layout.getAdapter().getItemCount();
317+
int position = displayPosition - 1;
318+
if(position < 0){
319+
position += cnt;
320+
}
321+
View view = getStackView();
322+
layout.getAdapter().onBindView(view, position);
323+
needRelayout = true;
324+
layout.addView(view);
325+
return view;
326+
}
314327

328+
/** 移除底层 */
329+
private void removeBottomView(){
330+
int cnt = layout.getAdapter().getItemCount();
331+
displayPosition -= 1;
332+
if(displayPosition < 0){
333+
displayPosition += cnt;
334+
}
335+
needRelayout = true;
336+
View view = layout.getChildAt(0);
337+
removeStackView(view);
338+
layout.getAdapter().onItemDisplay(displayPosition);
315339
}
316340

317341
@Override
@@ -357,27 +381,28 @@ float getTranslationX(){
357381

358382
void setTranslationX(float value){
359383
if(mAnimatorView != null){
360-
mAnimatorView.setTranslationX(mAnimatorView.getTranslationX()+value-lastValue);
384+
float trans = mAnimatorView.getTranslationX()+value-lastValue;
385+
mAnimatorView.setTranslationX(trans);
361386
}
362387
lastValue = value;
363388
}
364389

365-
void startAnimator(boolean needRemove,boolean needAdd,float transX, int distance, ValueAnimator.AnimatorUpdateListener listener){
366-
int duration = needAdd ? 500 : (int)(Math.abs(transX)/distance*150);
367-
needAddBottomView = needAdd;
368-
needRemoveTopView = needRemove;
390+
void startAnimator(boolean needRemoveTop,boolean needAddBottom,float transX, int distance, ValueAnimator.AnimatorUpdateListener listener){
391+
int duration = needAddBottom ? 400 : (int)(Math.abs(transX)/distance*100);
392+
needAddBottomView = needAddBottom;
393+
needRemoveTopView = needRemoveTop;
369394
animator = ValueAnimator.ofFloat(0f, transX).setDuration(duration);
370-
animator.setInterpolator(needAdd ? interpolatorAuto : interpolator);
395+
animator.setInterpolator(needAddBottom ? interpolatorAuto : interpolator);
371396
animator.addUpdateListener(listener);
372397
animator.start();
373398
}
374399

375400
void endAnimator(StackHelper helper){
376401
if(needRemoveTopView) {
377402
helper.removeStackView(mAnimatorView);
378-
needRemoveTopView = false;
379403
}
380404
animator.removeAllUpdateListeners();
405+
needRemoveTopView = false;
381406
lastValue = 0f;
382407
mAnimatorView = null;
383408
animator = null;
@@ -421,7 +446,7 @@ public void run() {
421446
}
422447
}
423448

424-
static boolean filterClick(){
449+
boolean filterClick(){
425450
long nowMills = System.currentTimeMillis();
426451
if(nowMills - clickMills > 500){
427452
clickMills = nowMills;
@@ -430,9 +455,11 @@ static boolean filterClick(){
430455
return false;
431456
}
432457

433-
static void log(String msg){
434-
StackTraceElement element = Thread.currentThread().getStackTrace()[3];
435-
Log.e("StackLayout",String.format("%1$s:%2$s(%3$s):%4$s",element.getClassName(),
436-
element.getMethodName(),element.getLineNumber(),msg));
458+
void log(String msg){
459+
if(debug) {
460+
StackTraceElement element = Thread.currentThread().getStackTrace()[3];
461+
Log.e("StackLayout", String.format("%1$s:%2$s(%3$s):%4$s", element.getClassName(),
462+
element.getMethodName(), element.getLineNumber(), msg));
463+
}
437464
}
438465
}

stacklayout/src/main/java/com/uis/stackview/StackLayout.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ public void setPosition(int position){
134134

135135
@Override
136136
public boolean onInterceptTouchEvent(MotionEvent event) {
137+
//stackHelper.log("act="+event.getActionMasked());
137138
int action = event.getActionMasked();
138139
switch (action) {
139140
case MotionEvent.ACTION_DOWN:
@@ -142,13 +143,17 @@ public boolean onInterceptTouchEvent(MotionEvent event) {
142143
downY = (int) event.getY();
143144
lastX = event.getX();
144145
break;
146+
//fixed inner view touch
147+
case MotionEvent.ACTION_MOVE:
148+
return stackHelper.canScroll(downX,downY,event.getX(),event.getY());
145149
default:
146150
}
147151
return super.onInterceptTouchEvent(event);
148152
}
149153

150154
@Override
151155
public boolean onTouchEvent(MotionEvent event) {
156+
//stackHelper.log("act="+event.getActionMasked());
152157
if(adapter == null || adapter.getItemCount() == 0){
153158
return false;
154159
}
@@ -170,11 +175,7 @@ public boolean onTouchEvent(MotionEvent event) {
170175
}
171176
break;
172177
case MotionEvent.ACTION_UP:
173-
if(downX == (int)lastX && adapter != null){
174-
if(StackHelper.filterClick()) {
175-
stackHelper.onItemClicked();
176-
}
177-
}
178+
handleItemClicked();
178179
case MotionEvent.ACTION_CANCEL:
179180
mVelocity.computeCurrentVelocity(1000, mMaximumVelocity);
180181
int velocity = (int) mVelocity.getXVelocity();
@@ -185,6 +186,14 @@ public boolean onTouchEvent(MotionEvent event) {
185186
return true;
186187
}
187188

189+
private void handleItemClicked(){
190+
if(adapter != null && downX == (int)lastX){
191+
if(stackHelper.filterClick()) {
192+
stackHelper.onItemClicked();
193+
}
194+
}
195+
}
196+
188197
public void requestParentDisallowInterceptTouchEvent() {
189198
final ViewParent parent = getParent();
190199
if (parent != null) {

0 commit comments

Comments
 (0)