Code example for MotionEvent

Methods: getEventTimegetRawXgetRawYgetXgetYoffsetLocation

0
        } 
        public void addMovement(MotionEvent event) {
            if (mEventBuf.size() == MAX_EVENTS) {
                mEventBuf.remove();
            } 
            mEventBuf.add(new MotionEventCopy(event.getX(), event.getY(), event.getEventTime()));
        } 
        public void computeCurrentVelocity(long timebase) {
            if (FlingTracker.DEBUG) {
                Slog.v("FlingTracker", "computing velocities for " + mEventBuf.size() + " events");
            } 
            mVX = mVY = 0;
            MotionEventCopy last = null;
            int i = 0;
            int j = 0;
            float totalweight = 0f;
            float weight = 10f;
            for (final Iterator<MotionEventCopy> iter = mEventBuf.descendingIterator();
                    iter.hasNext();) {
                final MotionEventCopy event = iter.next();
                if (last != null) {
                    final float dt = (float) (event.t - last.t) / timebase;
                    if (dt == 0) {
                        last = event;
                        continue; 
                    } 
                    final float dx = (event.x - last.x);
                    final float dy = (event.y - last.y);
                    if (FlingTracker.DEBUG) {
                        Slog.v("FlingTracker", String.format("   [%d] dx=%.1f dy=%.1f dt=%.0f vx=%.1f vy=%.1f",
                                i,
                                dx, dy, dt,
                                (dx/dt),
                                (dy/dt)
                                )); 
                    } 
                    mVX += weight * dx / dt;
                    mVY += weight * dy / dt;
                    totalweight += weight;
                    weight *= DECAY;
                    j++;
                } 
                last = event;
                i++;
            } 
 
            if (totalweight > 0) {
                mVX /= totalweight;
                mVY /= totalweight;
            } else { 
                if (DEBUG_NAN) {
                    Slog.v("FlingTracker", "computeCurrentVelocity warning: totalweight=0", 
                            new Throwable());
                } 
                // so as not to contaminate the velocities with NaN 
                mVX = mVY = 0;
            } 
 
            if (FlingTracker.DEBUG) {
                Slog.v("FlingTracker", "computed: vx=" + mVX + " vy=" + mVY);
            } 
        } 
        public float getXVelocity() { 
            if (Float.isNaN(mVX)) {
                if (DEBUG_NAN) {
                    Slog.v("FlingTracker", "warning: vx=NaN"); 
                } 
                mVX = 0;
            } 
            return mVX;
        } 
        public float getYVelocity() { 
            if (Float.isNaN(mVY)) {
                if (DEBUG_NAN) {
                    Slog.v("FlingTracker", "warning: vx=NaN"); 
                } 
                mVY = 0;
            } 
            return mVY;
        } 
        public void recycle() { 
            mEventBuf.clear();
        } 
 
        static FlingTracker sTracker;
        static FlingTracker obtain() { 
            if (sTracker == null) {
                sTracker = new FlingTracker();
            } 
            return sTracker;
        } 
    } 
 
    private int[] mAbsPos = new int[2];
    PanelBar mBar;
 
    private final TimeListener mAnimationCallback = new TimeListener() {
        @Override 
        public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) { 
            animationTick(deltaTime); 
        } 
    }; 
 
    private final Runnable mStopAnimator = new Runnable() {
        @Override 
        public void run() { 
            if (mTimeAnimator != null && mTimeAnimator.isStarted()) { 
                mTimeAnimator.end(); 
                mRubberbanding = false; 
                mClosing = false; 
            } 
        } 
    }; 
 
    private float mVel, mAccel;
    private int mFullHeight = 0;
    private String mViewName;
    protected float mInitialTouchY;
    protected float mFinalTouchY;
 
    public void setRubberbandingEnabled(boolean enable) {
        mRubberbandingEnabled = enable;
    } 
 
    private void runPeekAnimation() { 
        if (DEBUG) LOG("peek to height=%.1f", mPeekHeight);
        if (mTimeAnimator.isStarted()) {
            return; 
        } 
        if (mPeekAnimator == null) {
            mPeekAnimator = ObjectAnimator.ofFloat(this, 
                    "expandedHeight", mPeekHeight)
                .setDuration(250);
        } 
        mPeekAnimator.start();
    } 
 
    private void animationTick(long dtms) {
        if (!mTimeAnimator.isStarted()) {
            // XXX HAX to work around bug in TimeAnimator.end() not resetting its last time 
            mTimeAnimator = new TimeAnimator();
            mTimeAnimator.setTimeListener(mAnimationCallback);
 
            if (mPeekAnimator != null) mPeekAnimator.cancel();
 
            mTimeAnimator.start();
 
            mRubberbanding = mRubberbandingEnabled // is it enabled at all?
                    && mExpandedHeight > getFullHeight() // are we past the end?
                    && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
            if (mRubberbanding) {
                mClosing = true;
            } else if (mVel == 0) {
                // if the panel is less than halfway open, close it 
                mClosing = (mFinalTouchY / getFullHeight()) < 0.5f;
            } else { 
                mClosing = mExpandedHeight > 0 && mVel < 0;
            } 
        } else if (dtms > 0) {
            final float dt = dtms * 0.001f;                  // ms -> s
            if (DEBUG) LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
            if (DEBUG) LOG("tick: before: h=%d", (int) mExpandedHeight);
 
            final float fh = getFullHeight();
            boolean braking = false;
            if (BRAKES) {
                if (mClosing) {
                    braking = mExpandedHeight <= mCollapseBrakingDistancePx;
                    mAccel = braking ? 10*mCollapseAccelPx : -mCollapseAccelPx;
                } else { 
                    braking = mExpandedHeight >= (fh-mExpandBrakingDistancePx);
                    mAccel = braking ? 10*-mExpandAccelPx : mExpandAccelPx;
                } 
            } else { 
                mAccel = mClosing ? -mCollapseAccelPx : mExpandAccelPx;
            } 
 
            mVel += mAccel * dt;
 
            if (braking) {
                if (mClosing && mVel > -mBrakingSpeedPx) {
                    mVel = -mBrakingSpeedPx;
                } else if (!mClosing && mVel < mBrakingSpeedPx) {
                    mVel = mBrakingSpeedPx;
                } 
            } else { 
                if (mClosing && mVel > -mFlingCollapseMinVelocityPx) {
                    mVel = -mFlingCollapseMinVelocityPx;
                } else if (!mClosing && mVel > mFlingGestureMaxOutputVelocityPx) {
                    mVel = mFlingGestureMaxOutputVelocityPx;
                } 
            } 
 
            float h = mExpandedHeight + mVel * dt;
 
            if (mRubberbanding && h < fh) {
                h = fh;
            } 
 
            if (DEBUG) LOG("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
 
            setExpandedHeightInternal(h);
 
            mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
 
            if (mVel == 0
                    || (mClosing && mExpandedHeight == 0)
                    || ((mRubberbanding || !mClosing) && mExpandedHeight == fh)) {
                post(mStopAnimator);
            } 
        } else { 
            Slog.v(TAG, "animationTick called with dtms=" + dtms + "; nothing to do (h="
                    + mExpandedHeight + " v=" + mVel + ")");
        } 
    } 
 
    public PanelView(Context context, AttributeSet attrs) {
        super(context, attrs);
 
        mTimeAnimator = new TimeAnimator();
        mTimeAnimator.setTimeListener(mAnimationCallback);
    } 
 
    private void loadDimens() { 
        final Resources res = getContext().getResources();
 
        mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
        mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
        mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
        mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
 
        mFlingGestureMinDistPx = res.getDimension(R.dimen.fling_gesture_min_dist);
 
        mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
        mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
 
        mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
        mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
 
        mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
 
        mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
 
        mPeekHeight = res.getDimension(R.dimen.peek_height) 
            + getPaddingBottom() // our window might have a dropshadow
            - (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
    } 
 
    private void trackMovement(MotionEvent event) {
        // Add movement to velocity tracker using raw screen X and Y coordinates instead 
        // of window coordinates because the window frame may be moving at the same time. 
        float deltaX = event.getRawX() - event.getX();
        float deltaY = event.getRawY() - event.getY();
        event.offsetLocation(deltaX, deltaY);
        if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
        event.offsetLocation(-deltaX, -deltaY);
    } 
 
    // Pass all touches along to the handle, allowing the user to drag the panel closed from its interior 
    @Override 
    public boolean onTouchEvent(MotionEvent event) {