Implemented show and hide animations for "Your train" card. ListView selection is still wonky.
This commit is contained in:
parent
94ed29467d
commit
9bd040c3e8
@ -39,7 +39,7 @@ import com.actionbarsherlock.view.MenuInflater;
|
|||||||
import com.actionbarsherlock.view.MenuItem;
|
import com.actionbarsherlock.view.MenuItem;
|
||||||
import com.dougkeen.bart.BartRunnerApplication;
|
import com.dougkeen.bart.BartRunnerApplication;
|
||||||
import com.dougkeen.bart.R;
|
import com.dougkeen.bart.R;
|
||||||
import com.dougkeen.bart.controls.SwipeDismissTouchListener;
|
import com.dougkeen.bart.controls.SwipeHelper;
|
||||||
import com.dougkeen.bart.controls.Ticker;
|
import com.dougkeen.bart.controls.Ticker;
|
||||||
import com.dougkeen.bart.controls.YourTrainLayout;
|
import com.dougkeen.bart.controls.YourTrainLayout;
|
||||||
import com.dougkeen.bart.data.DepartureArrayAdapter;
|
import com.dougkeen.bart.data.DepartureArrayAdapter;
|
||||||
@ -189,9 +189,8 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
|
|
||||||
mYourTrainSection = (YourTrainLayout) findViewById(R.id.yourTrainSection);
|
mYourTrainSection = (YourTrainLayout) findViewById(R.id.yourTrainSection);
|
||||||
mYourTrainSection.setOnClickListener(mYourTrainSectionClickListener);
|
mYourTrainSection.setOnClickListener(mYourTrainSectionClickListener);
|
||||||
mYourTrainSection.setOnTouchListener(new SwipeDismissTouchListener(
|
mSwipeHelper = new SwipeHelper(mYourTrainSection, null,
|
||||||
mYourTrainSection, null,
|
new SwipeHelper.OnDismissCallback() {
|
||||||
new SwipeDismissTouchListener.OnDismissCallback() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onDismiss(View view, Object token) {
|
public void onDismiss(View view, Object token) {
|
||||||
dismissYourTrainSelection();
|
dismissYourTrainSelection();
|
||||||
@ -201,7 +200,8 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
mActionMode.finish();
|
mActionMode.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
mYourTrainSection.setOnTouchListener(mSwipeHelper);
|
||||||
|
|
||||||
refreshBoardedDeparture();
|
refreshBoardedDeparture();
|
||||||
|
|
||||||
@ -363,6 +363,8 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
|
|
||||||
private YourTrainLayout mYourTrainSection;
|
private YourTrainLayout mYourTrainSection;
|
||||||
|
|
||||||
|
private SwipeHelper mSwipeHelper;
|
||||||
|
|
||||||
protected DepartureArrayAdapter getListAdapter() {
|
protected DepartureArrayAdapter getListAdapter() {
|
||||||
return mDeparturesAdapter;
|
return mDeparturesAdapter;
|
||||||
}
|
}
|
||||||
@ -480,7 +482,7 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
mYourTrainSection.updateFromDeparture(boardedDeparture);
|
mYourTrainSection.updateFromDeparture(boardedDeparture);
|
||||||
|
|
||||||
if (currentVisibility != View.VISIBLE) {
|
if (currentVisibility != View.VISIBLE) {
|
||||||
showYourTrainSection(mYourTrainSection);
|
showYourTrainSection();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mActionMode == null) {
|
if (mActionMode == null) {
|
||||||
@ -678,7 +680,7 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
startService(intent);
|
startService(intent);
|
||||||
return true;
|
return true;
|
||||||
} else if (itemId == R.id.delete) {
|
} else if (itemId == R.id.delete) {
|
||||||
dismissYourTrainSelection();
|
mSwipeHelper.dismissWithAnimation(true);
|
||||||
mode.finish();
|
mode.finish();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -770,11 +772,37 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
refreshBoardedDeparture();
|
refreshBoardedDeparture();
|
||||||
|
|
||||||
getListAdapter().notifyDataSetChanged();
|
getListAdapter().notifyDataSetChanged();
|
||||||
|
|
||||||
|
refreshListSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void refreshListSelection() {
|
||||||
|
getListView().clearChoices();
|
||||||
|
final Departure targetDeparture;
|
||||||
|
if (isDepartureActionModeActive() && mSelectedDeparture != null) {
|
||||||
|
targetDeparture = mSelectedDeparture;
|
||||||
|
} else {
|
||||||
|
targetDeparture = ((BartRunnerApplication) getApplication())
|
||||||
|
.getBoardedDeparture();
|
||||||
|
}
|
||||||
|
for (int i = getListAdapter().getCount() - 1; i >= 0; i--) {
|
||||||
|
if (getListAdapter().getItem(i).equals(targetDeparture)) {
|
||||||
|
final int selectedIndex = i;
|
||||||
|
getListView().post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
getListView().setSelection(selectedIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getListView().requestLayout();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(final String errorMessage) {
|
public void onError(final String errorMessage) {
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@ -816,11 +844,12 @@ public class ViewDeparturesActivity extends SActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void hideYourTrainSection() {
|
private void hideYourTrainSection() {
|
||||||
findViewById(R.id.yourTrainSection).setVisibility(View.GONE);
|
mYourTrainSection.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showYourTrainSection(final YourTrainLayout yourTrainSection) {
|
private void showYourTrainSection() {
|
||||||
yourTrainSection.setVisibility(View.VISIBLE);
|
mYourTrainSection.setVisibility(View.VISIBLE);
|
||||||
|
mSwipeHelper.showWithAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isYourTrainActionModeActive() {
|
private boolean isYourTrainActionModeActive() {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2012 Doug Keen
|
||||||
* Copyright 2012 Roman Nurik
|
* Copyright 2012 Roman Nurik
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
@ -18,23 +19,27 @@
|
|||||||
|
|
||||||
package com.dougkeen.bart.controls;
|
package com.dougkeen.bart.controls;
|
||||||
|
|
||||||
|
import static com.nineoldandroids.view.ViewHelper.setAlpha;
|
||||||
|
import static com.nineoldandroids.view.ViewHelper.setTranslationX;
|
||||||
|
import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.VelocityTracker;
|
import android.view.VelocityTracker;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.MeasureSpec;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.dougkeen.bart.model.Constants;
|
||||||
import com.nineoldandroids.animation.Animator;
|
import com.nineoldandroids.animation.Animator;
|
||||||
import com.nineoldandroids.animation.AnimatorListenerAdapter;
|
import com.nineoldandroids.animation.AnimatorListenerAdapter;
|
||||||
import com.nineoldandroids.animation.ValueAnimator;
|
import com.nineoldandroids.animation.ValueAnimator;
|
||||||
|
|
||||||
import static com.nineoldandroids.view.ViewHelper.setAlpha;
|
|
||||||
import static com.nineoldandroids.view.ViewHelper.setTranslationX;
|
|
||||||
import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link android.view.View.OnTouchListener} that makes any {@link View}
|
* A utility class for animating the dismissal of a view (with 'onDismiss'
|
||||||
* dismissable when the user swipes (drags her finger) horizontally across the
|
* callback). Also, a {@link android.view.View.OnTouchListener} that makes any
|
||||||
* view.
|
* {@link View} dismissable when the user swipes (drags her finger) horizontally
|
||||||
|
* across the view.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* <em>For {@link android.widget.ListView} list items that don't manage their own touch events
|
* <em>For {@link android.widget.ListView} list items that don't manage their own touch events
|
||||||
@ -49,10 +54,10 @@ import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* view.setOnTouchListener(new SwipeDismissTouchListener(view, null, // Optional
|
* view.setOnTouchListener(new SwipeDismisser(view, null, // Optional
|
||||||
* // token/cookie
|
* // token/cookie
|
||||||
* // object
|
* // object
|
||||||
* new SwipeDismissTouchListener.OnDismissCallback() {
|
* new SwipeDismisser.OnDismissCallback() {
|
||||||
* public void onDismiss(View view, Object token) {
|
* public void onDismiss(View view, Object token) {
|
||||||
* parent.removeView(view);
|
* parent.removeView(view);
|
||||||
* }
|
* }
|
||||||
@ -61,7 +66,7 @@ import static com.nineoldandroids.view.ViewPropertyAnimator.animate;
|
|||||||
*
|
*
|
||||||
* @see SwipeDismissListViewTouchListener
|
* @see SwipeDismissListViewTouchListener
|
||||||
*/
|
*/
|
||||||
public class SwipeDismissTouchListener implements View.OnTouchListener {
|
public class SwipeHelper implements View.OnTouchListener {
|
||||||
// Cached ViewConfiguration and system-wide constant values
|
// Cached ViewConfiguration and system-wide constant values
|
||||||
private int mSlop;
|
private int mSlop;
|
||||||
private int mMinFlingVelocity;
|
private int mMinFlingVelocity;
|
||||||
@ -81,9 +86,8 @@ public class SwipeDismissTouchListener implements View.OnTouchListener {
|
|||||||
private float mTranslationX;
|
private float mTranslationX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The callback interface used by {@link SwipeDismissTouchListener} to
|
* The callback interface used by {@link SwipeHelper} to inform its
|
||||||
* inform its client about a successful dismissal of the view for which it
|
* client about a successful dismissal of the view for which it was created.
|
||||||
* was created.
|
|
||||||
*/
|
*/
|
||||||
public interface OnDismissCallback {
|
public interface OnDismissCallback {
|
||||||
/**
|
/**
|
||||||
@ -110,8 +114,7 @@ public class SwipeDismissTouchListener implements View.OnTouchListener {
|
|||||||
* The callback to trigger when the user has indicated that she
|
* The callback to trigger when the user has indicated that she
|
||||||
* would like to dismiss this view.
|
* would like to dismiss this view.
|
||||||
*/
|
*/
|
||||||
public SwipeDismissTouchListener(View view, Object token,
|
public SwipeHelper(View view, Object token, OnDismissCallback callback) {
|
||||||
OnDismissCallback callback) {
|
|
||||||
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
|
ViewConfiguration vc = ViewConfiguration.get(view.getContext());
|
||||||
mSlop = vc.getScaledTouchSlop();
|
mSlop = vc.getScaledTouchSlop();
|
||||||
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
|
mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
|
||||||
@ -125,6 +128,7 @@ public class SwipeDismissTouchListener implements View.OnTouchListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||||
|
Log.v(Constants.TAG, "onTouch()");
|
||||||
// offset because the view is translated during swipe
|
// offset because the view is translated during swipe
|
||||||
motionEvent.offsetLocation(mTranslationX, 0);
|
motionEvent.offsetLocation(mTranslationX, 0);
|
||||||
|
|
||||||
@ -164,15 +168,7 @@ public class SwipeDismissTouchListener implements View.OnTouchListener {
|
|||||||
}
|
}
|
||||||
if (dismiss) {
|
if (dismiss) {
|
||||||
// dismiss
|
// dismiss
|
||||||
animate(mView)
|
dismissWithAnimation(dismissRight);
|
||||||
.translationX(dismissRight ? mViewWidth : -mViewWidth)
|
|
||||||
.alpha(0).setDuration(mAnimationTime)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
performDismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// cancel
|
// cancel
|
||||||
animate(mView).translationX(0).alpha(1)
|
animate(mView).translationX(0).alpha(1)
|
||||||
@ -222,6 +218,17 @@ public class SwipeDismissTouchListener implements View.OnTouchListener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void dismissWithAnimation(boolean dismissRight) {
|
||||||
|
animate(mView).translationX(dismissRight ? mViewWidth : -mViewWidth)
|
||||||
|
.alpha(0).setDuration(mAnimationTime)
|
||||||
|
.setListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
performDismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void performDismiss() {
|
private void performDismiss() {
|
||||||
// Animate the dismissed view to zero-height and then fire the dismiss
|
// Animate the dismissed view to zero-height and then fire the dismiss
|
||||||
// callback.
|
// callback.
|
||||||
@ -257,4 +264,46 @@ public class SwipeDismissTouchListener implements View.OnTouchListener {
|
|||||||
|
|
||||||
animator.start();
|
animator.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showWithAnimation() {
|
||||||
|
final int measureSpec = MeasureSpec.makeMeasureSpec(
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY);
|
||||||
|
mView.measure(measureSpec, measureSpec);
|
||||||
|
mViewWidth = mView.getMeasuredWidth();
|
||||||
|
final int viewHeight = mView.getMeasuredHeight();
|
||||||
|
setAlpha(mView, 0f);
|
||||||
|
|
||||||
|
final ViewGroup.LayoutParams lp = mView.getLayoutParams();
|
||||||
|
lp.width = mViewWidth;
|
||||||
|
|
||||||
|
setTranslationX(mView, mViewWidth);
|
||||||
|
|
||||||
|
// Grow space
|
||||||
|
ValueAnimator animator = ValueAnimator.ofInt(1, viewHeight)
|
||||||
|
.setDuration(mAnimationTime);
|
||||||
|
|
||||||
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
// Reset view presentation
|
||||||
|
// mView.requestLayout();
|
||||||
|
|
||||||
|
// Swipe view into space that opened up
|
||||||
|
animate(mView).translationX(0).alpha(1)
|
||||||
|
.setDuration(mAnimationTime)
|
||||||
|
.setListener(new AnimatorListenerAdapter() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||||
|
lp.height = (Integer) valueAnimator.getAnimatedValue();
|
||||||
|
mView.setLayoutParams(lp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
animator.start();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user