Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4911300a authored by Hongwei Wang's avatar Hongwei Wang
Browse files

Crossfade when drop to the position

Bug: 10686781
Change-Id: I8e5546b1eb8f914054e9525e8d763928d35836a8
parent f796309c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -45,5 +45,11 @@
            android:layout_marginTop="@dimen/empty_message_top_margin"
            android:textColor="?android:attr/textColorSecondary"
            android:textAppearance="?android:attr/textAppearanceLarge"/>

        <ImageView
            android:id="@+id/contact_tile_drag_shadow_overlay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"/>
    </FrameLayout>
</LinearLayout>
+2 −2
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
  ~ limitations under the License
  -->
<resources>
    <integer name="fade_duration">250</integer>
    <integer name="fade_duration">300</integer>

    <!-- Swipe constants -->
    <integer name="swipe_escape_velocity">100</integer>
+19 −46
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

@@ -66,7 +67,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
    private static final String TAG = PhoneFavoriteFragment.class.getSimpleName();
    private static final boolean DEBUG = true;

    private static final int ANIMATION_DURATION = 300;
    private int mAnimationDuration;

    /**
     * Used with LoaderManager.
@@ -182,6 +183,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
        if (DEBUG) Log.d(TAG, "onCreate()");
        super.onCreate(savedState);

        mAnimationDuration = getResources().getInteger(R.integer.fade_duration);
        mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(),
                this, 1);
        final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity());
@@ -213,6 +215,10 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
        mListView.setOnItemSwipeListener(mContactTileAdapter);
        mListView.setOnDragDropListener(mContactTileAdapter);

        final ImageView dragShadowOverlay =
                (ImageView) listLayout.findViewById(R.id.contact_tile_drag_shadow_overlay);
        mListView.setDragShadowOverlay(dragShadowOverlay);

        mEmptyView = inflater.inflate(R.layout.phone_no_favorites, mListView, false);

        mShowAllContactsButton = inflater.inflate(R.layout.show_all_contact_button, mListView,
@@ -372,26 +378,14 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
            final ContactEntry entry = list.get(i);
            final long itemId = mContactTileAdapter.getAdjustedItemId(entry.id);

            // Skip animation for this view if the caller specified that it should be
            // kept in place
            if (containsId(idsInPlace, itemId)) continue;

            Integer startLeft = mItemIdLeftMap.get(itemId);
            int left = child.getLeft();
            if (DEBUG) {
                Log.d(TAG, "Found itemId: " + itemId + " for tileview child " + i +
                        " Left: " + left);
            }
            if (startLeft != null) {
                if (startLeft != left) {
                    int delta = startLeft - left;
                    child.setTranslationX(delta);
                    child.animate().setDuration(ANIMATION_DURATION).translationX(0);
            if (containsId(idsInPlace, itemId)) {
                child.setAlpha(0.0f);
                child.animate().alpha(1.0f)
                        .setDuration(mAnimationDuration)
                        .start();
                break;
            }
        }
            // No need to worry about horizontal offsets of new views that come into view since
            // there is no horizontal scrolling involved.
        }
    }

    /*
@@ -424,33 +418,12 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen

                    final long itemId = mAdapter.getItemId(position);

                    // Skip animation for this view if the caller specified that it should be
                    // kept in place
                    if (containsId(idsInPlace, itemId)) continue;

                    Integer startTop = mItemIdTopMap.get(itemId);
                    final int top = child.getTop();
                    if (DEBUG) {
                        Log.d(TAG, "Found itemId: " + itemId + " for listview child " + i +
                                " Top: " + top);
                    }
                    int delta = 0;
                    if (startTop != null) {
                        if (startTop != top) {
                            delta = startTop - top;
                        }
                    } else if (!mItemIdLeftMap.containsKey(itemId)) {
                        // Animate new views along with the others. The catch is that they did not
                        // exist in the start state, so we must calculate their starting position
                        // based on neighboring views.
                        int childHeight = child.getHeight() + mListView.getDividerHeight();
                        startTop = top + (i > 0 ? childHeight : -childHeight);
                        delta = startTop - top;
                    }

                    if (delta != 0) {
                        child.setTranslationY(delta);
                        child.animate().setDuration(ANIMATION_DURATION).translationY(0);
                    if (containsId(idsInPlace, itemId)) {
                        child.setAlpha(0.0f);
                        child.animate().alpha(1.0f)
                                .setDuration(mAnimationDuration)
                                .start();
                        break;
                    }
                }
                mItemIdTopMap.clear();
+66 −18
Original line number Diff line number Diff line
@@ -17,11 +17,11 @@

package com.android.dialer.list;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
@@ -29,6 +29,8 @@ import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;

import com.android.dialer.R;
@@ -66,7 +68,10 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
    private boolean mIsDragScrollerRunning = false;
    private int mTouchDownForDragStartX;
    private int mTouchDownForDragStartY;

    private Bitmap mDragShadowBitmap;
    private ImageView mDragShadowOverlay;
    private int mAnimationDuration;

    // X and Y offsets inside the item from where the user grabbed to the
    // child's left coordinate. This is used to aid in the drawing of the drag shadow.
@@ -78,8 +83,7 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
    private int mDragShadowWidth;
    private int mDragShadowHeight;

    private final int DRAG_SHADOW_ALPHA = 180;
    private final Paint mPaint = new Paint();
    private final float DRAG_SHADOW_ALPHA = 0.7f;

    /**
     * {@link #mTopScrollBound} and {@link mBottomScrollBound} will be
@@ -99,6 +103,28 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        }
    };

    private final AnimatorListenerAdapter mDragShadowOverAnimatorListener =
            new AnimatorListenerAdapter() {
        private void recycleDragShadow() {
            if (mDragShadowBitmap != null) {
                mDragShadowBitmap.recycle();
                mDragShadowBitmap = null;
            }
            mDragShadowOverlay.setVisibility(GONE);
            mDragShadowOverlay.setImageBitmap(null);
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            recycleDragShadow();
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            recycleDragShadow();
        }
    };

    public PhoneFavoriteListView(Context context) {
        this(context, null);
    }
@@ -109,12 +135,12 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba

    public PhoneFavoriteListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mAnimationDuration = context.getResources().getInteger(R.integer.fade_duration);
        mDensityScale = getResources().getDisplayMetrics().density;
        mTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
        mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this,
                mDensityScale, mTouchSlop);
        setItemsCanFocus(true);
        mPaint.setAlpha(DRAG_SHADOW_ALPHA);
    }

    @Override
@@ -251,7 +277,9 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
                ensureScrollHandler();
                mScrollHandler.removeCallbacks(mDragScroller);
                mIsDragScrollerRunning = false;
                if (action != DragEvent.ACTION_DRAG_EXITED) {
                // Either it's been a successful drop or it's ended with out drop.
                if (action == DragEvent.ACTION_DROP ||
                        (action == DragEvent.ACTION_DRAG_ENDED && !event.getResult())) {
                    handleDragFinished(eX, eY);
                }
                break;
@@ -262,13 +290,8 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        return true;
    }

    @Override
    public void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        // Draw the drag shadow at its last known location if the drag shadow exists.
        if (mDragShadowBitmap != null) {
            canvas.drawBitmap(mDragShadowBitmap, mDragShadowLeft, mDragShadowTop, mPaint);
        }
    public void setDragShadowOverlay(ImageView overlay) {
        mDragShadowOverlay = overlay;
    }

    /**
@@ -292,6 +315,14 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        }
    }

    private FrameLayout.LayoutParams getDragShadowLayoutParams() {
        final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
                mDragShadowWidth, mDragShadowHeight);
        lp.leftMargin = mDragShadowLeft;
        lp.topMargin = mDragShadowTop;
        return lp;
    }

    /**
     * @return True if the drag is started.
     */
@@ -307,6 +338,11 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        if (itemIndex != -1 && mOnDragDropListener != null) {
            final PhoneFavoriteTileView tileView =
                    (PhoneFavoriteTileView) tile.getViewAtPosition(x, y);
            if (mDragShadowOverlay == null) {
                return false;
            }

            mDragShadowOverlay.clearAnimation();
            mDragShadowBitmap = createDraggedChildBitmap(tileView);
            if (mDragShadowBitmap == null) {
                return false;
@@ -321,9 +357,16 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
                mDragShadowLeft = tileView.getLeft() + tileView.getParentRow().getLeft();
                mDragShadowTop = tileView.getTop() + tileView.getParentRow().getTop();
            }

            mDragShadowWidth = tileView.getWidth();
            mDragShadowHeight = tileView.getHeight();

            mDragShadowOverlay.setImageBitmap(mDragShadowBitmap);
            mDragShadowOverlay.setVisibility(VISIBLE);
            mDragShadowOverlay.setAlpha(DRAG_SHADOW_ALPHA);

            mDragShadowOverlay.setLayoutParams(getDragShadowLayoutParams());

            // x and y passed in are the coordinates of where the user has touched down, calculate
            // the offset to the top left coordinate of the dragged child.  This will be used for
            // drawing the drag shadow.
@@ -350,8 +393,10 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        mDragShadowLeft = x - mTouchOffsetToChildLeft;
        mDragShadowTop = y - mTouchOffsetToChildTop;

        // invalidate to trigger a redraw of the drag shadow.
        invalidate();
        // Draw the drag shadow at its last known location if the drag shadow exists.
        if (mDragShadowOverlay != null) {
            mDragShadowOverlay.setLayoutParams(getDragShadowLayoutParams());
        }

        final ContactTileRow tile = (ContactTileRow) child;
        final int itemIndex = tile.getItemIndex(x, y);
@@ -365,9 +410,12 @@ public class PhoneFavoriteListView extends ListView implements SwipeHelperCallba
        mDragShadowLeft = x - mTouchOffsetToChildLeft;
        mDragShadowTop = y - mTouchOffsetToChildTop;

        if (mDragShadowBitmap != null) {
            mDragShadowBitmap.recycle();
            mDragShadowBitmap = null;
        if (mDragShadowOverlay != null) {
            mDragShadowOverlay.clearAnimation();
            mDragShadowOverlay.animate().alpha(0.0f)
                    .setDuration(mAnimationDuration)
                    .setListener(mDragShadowOverAnimatorListener)
                    .start();
        }

        if (mOnDragDropListener != null) {
+6 −4
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.view.View;
import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.list.ContactEntry;
import com.android.contacts.common.list.ContactTileView;
import com.android.dialer.R;
import com.android.dialer.list.PhoneFavoritesTileAdapter.ContactTileRow;
import com.android.dialer.list.PhoneFavoritesTileAdapter.ViewTypes;

@@ -47,7 +48,7 @@ public abstract class PhoneFavoriteTileView extends ContactTileView {
    private static final boolean DEBUG = false;

    /** Length of all animations in miniseconds. */
    private static final int ANIMATION_LENGTH = 300;
    private int mAnimationDuration;

    /** The view that holds the front layer of the favorite contact card. */
    private View mFavoriteContactCard;
@@ -66,6 +67,7 @@ public abstract class PhoneFavoriteTileView extends ContactTileView {

    public PhoneFavoriteTileView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mAnimationDuration = context.getResources().getInteger(R.integer.fade_duration);
    }

    public ContactTileRow getParentRow() {
@@ -131,7 +133,7 @@ public abstract class PhoneFavoriteTileView extends ContactTileView {
        mRemovalDialogue.setVisibility(VISIBLE);
        mRemovalDialogue.setAlpha(0f);
        final ObjectAnimator fadeIn = ObjectAnimator.ofFloat(mRemovalDialogue, "alpha",
                1.f).setDuration(ANIMATION_LENGTH);
                1.f).setDuration(mAnimationDuration);

        fadeIn.addListener(new AnimatorListenerAdapter() {
            @Override
@@ -157,9 +159,9 @@ public abstract class PhoneFavoriteTileView extends ContactTileView {

        // Animates back the favorite contact card.
        final ObjectAnimator fadeIn = ObjectAnimator.ofFloat(mFavoriteContactCard, "alpha", 1.f).
                setDuration(ANIMATION_LENGTH);
                setDuration(mAnimationDuration);
        final ObjectAnimator moveBack = ObjectAnimator.ofFloat(mFavoriteContactCard, "translationX",
                0.f).setDuration(ANIMATION_LENGTH);
                0.f).setDuration(mAnimationDuration);

        final AnimatorSet animSet = new AnimatorSet();

Loading