com.albedinsky.android.support.ui.HorizontalPullHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.albedinsky.android.support.ui.HorizontalPullHelper.java

Source

/*
 * =================================================================================================
 *                    Copyright (C) 2014 Martin Albedinsky [Wolf-ITechnologies]
 * =================================================================================================
 *         Licensed under the Apache License, Version 2.0 or later (further "License" only).
 * -------------------------------------------------------------------------------------------------
 * You may use this file only in compliance with the License. More details and copy of this License 
 * you may obtain at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * You can redistribute, modify or publish any part of the code written within this file but as it 
 * is described in the License, the software distributed under the License is distributed on an 
 * "AS IS" BASIS, WITHOUT WARRANTIES or CONDITIONS OF ANY KIND.
 * 
 * See the License for the specific language governing permissions and limitations under the License.
 * =================================================================================================
 */
package com.albedinsky.android.support.ui;

import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;

/**
 * Implementation of {@link com.albedinsky.android.support.ui.PullHelper} to support pulling of
 * scrollable views which has {@link com.albedinsky.android.support.ui.widget.Pullable#HORIZONTAL}
 * orientation like {@link android.support.v4.view.ViewPager} or {@link android.widget.HorizontalScrollView}.
 * <p>
 * The pull is performed on these views by offsetting theirs original top/bottom positions by
 * {@link View#offsetLeftAndRight(int)} (int)} by deltas computed from the {@link android.view.MotionEvent}s
 * passed to the HorizontalPullHelper for the changes in {@link android.view.MotionEvent#getY()}.
 *
 * @author Martin Albedinsky
 */
final class HorizontalPullHelper extends PullHelper {

    /**
     * Interface ===================================================================================
     */

    /**
     * Constants ===================================================================================
     */

    /**
     * Log TAG.
     */
    // private static final String TAG = "HorizontalPullHelper";

    /**
     * Flag indicating whether the output trough log-cat is enabled or not.
     */
    // private static final boolean LOG_ENABLED = true;

    /**
     * Flag indicating whether the debug output trough log-cat is enabled or not.
     */
    // private static final boolean DEBUG_ENABLED = true;

    /**
     * Static members ==============================================================================
     */

    /**
     * Members =====================================================================================
     */

    /**
     * Last touch X coordinate used to compute delta against the new touch event.
     */
    private float mTouchLastX = 0;

    /**
     * Flag indicating whether this helper is expanding pull of the pullable view or collapsing it.
     */
    private boolean mExpandingPull;

    /**
     * Constructors ================================================================================
     */

    /**
     * Creates a new instance of HorizontalPullHelper to manage horizontal pull offsetting of the
     * given <var>pullableView</var>.
     *
     * @param pullableView The view of which pull to manage.
     */
    HorizontalPullHelper(View pullableView) {
        super(pullableView);
    }

    /**
     * Methods =====================================================================================
     */

    /**
     * Public --------------------------------------------------------------------------------------
     */

    /**
     * Getters + Setters ---------------------------------------------------------------------------
     */

    /**
     * Protected -----------------------------------------------------------------------------------
     */

    /**
     */
    @Override
    int getPullableViewSize() {
        return mView.getWidth();
    }

    /**
     */
    @Override
    void offsetPullableViewBy(int offset) {
        switch (mState) {
        case STATE_PULLING_AT_START:
            if (isPullVisible(PullController.START)) {
                mView.offsetLeftAndRight(offset);
            }
            break;
        case STATE_PULLING_AT_END:
            if (isPullVisible(PullController.END)) {
                mView.offsetLeftAndRight(offset);
            }
            break;
        }
    }

    /**
     */
    @Override
    boolean isAllowedVelocity(VelocityTracker tracker, float minVelocity) {
        return Math.abs(tracker.getXVelocity()) >= minVelocity;
    }

    /**
     */
    @Override
    void dispatchPullInitiated(MotionEvent event) {
        super.dispatchPullInitiated(event);
        switch (mState) {
        case STATE_PULLING_AT_START:
            this.mExpandingPull = mTouchLastX <= event.getX();
        case STATE_PULLING_AT_END:
            this.mExpandingPull = mTouchLastX > event.getX();
        }
        this.mTouchLastX = event.getX();
    }

    /**
     */
    @Override
    void dispatchPullPerformed(MotionEvent event) {
        super.dispatchPullPerformed(event);
        this.updateTouchLastX(event);
    }

    /**
     */
    @Override
    void dispatchPullCollapsed() {
        super.dispatchPullCollapsed();
        this.mTouchLastX = 0;
    }

    /**
     */
    @Override
    boolean shouldStartPull(MotionEvent event) {
        switch (mState) {
        case STATE_PULLING_AT_START:
            return mTouchLastX < event.getX();
        case STATE_PULLING_AT_END:
            return mTouchLastX > event.getX();
        }
        return false;
    }

    /**
     */
    @Override
    float computePullOffset(MotionEvent event) {
        final float delta = event.getX() - mTouchLastX;
        final float absDelta = Math.abs(delta);
        // Remove the shaking effect during slow pull.
        switch (mState) {
        case STATE_PULLING_AT_START:
            if ((mExpandingPull && delta < 0 && absDelta < mMinDeltaToChangePullDirection)
                    || (!mExpandingPull && delta > 0 && absDelta < mMinDeltaToChangePullDirection)) {
                this.mExpandingPull = mTouchLastX < event.getX();
                return 0;
            }
            this.mExpandingPull = mTouchLastX < event.getX();
            break;
        case STATE_PULLING_AT_END:
            if ((mExpandingPull && delta > 0 && absDelta < mMinDeltaToChangePullDirection)
                    || (!mExpandingPull && delta < 0 && absDelta < mMinDeltaToChangePullDirection)) {
                this.mExpandingPull = mTouchLastX > event.getX();
                return 0;
            }
            this.mExpandingPull = mTouchLastX > event.getX();
        }
        return Math.min(absDelta, mMaxPullDelta) * (delta > 0 ? 1 : -1);
    }

    /**
     */
    @Override
    boolean shouldExpandPull(MotionEvent event) {
        switch (mState) {
        case STATE_PULLING_AT_START:
            return event.getX() > mTouchLastX;
        case STATE_PULLING_AT_END:
            return event.getX() < mTouchLastX;
        }
        return false;
    }

    /**
     */
    @Override
    boolean shouldCollapsePull(MotionEvent event) {
        switch (mState) {
        case STATE_PULLING_AT_START:
            return event.getX() < mTouchLastX;
        case STATE_PULLING_AT_END:
            return event.getX() > mTouchLastX;
        }
        return false;
    }

    /**
     */
    @Override
    boolean shouldCancelPull(MotionEvent event) {
        switch (mState) {
        case STATE_PULLING_AT_START:
            return mTouchLastX > event.getX();
        case STATE_PULLING_AT_END:
            return mTouchLastX < event.getX();
        }
        return true;
    }

    /**
     */
    @Override
    boolean hasTouchChanged(MotionEvent event) {
        return event.getX() != mTouchLastX;
    }

    /**
     */
    @Override
    float computeOverScroll(int scrollX, int scrollY, boolean clampedX, boolean clampedY, VelocityTracker tracker,
            int units) {
        if (scrollX != 0 && clampedX) {
            return tracker.getXVelocity() / (units * 0.05f);
        }
        return 0;
    }

    /**
     * Private -------------------------------------------------------------------------------------
     */

    /**
     * Updates a value of the last touch X coordinate from the specified motion <var>event</var>.
     *
     * @param event The motion event from which to obtain X coordinate.
     */
    private void updateTouchLastX(MotionEvent event) {
        this.mTouchLastX = event.getX();
    }

    /**
     * Inner classes ===============================================================================
     */
}