예제 #1
0
  /** 画面サイズから自位置を決定します。 */
  private void updateViewLayout() {
    cancelAnimation();

    // 前の画面座標を保存
    final int oldScreenHeight = mMetrics.heightPixels;
    final int oldScreenWidth = mMetrics.widthPixels;
    final int oldPositionLimitWidth = mPositionLimitRect.width();
    final int oldPositionLimitHeight = mPositionLimitRect.height();

    // 新しい座標情報に切替
    mWindowManager.getDefaultDisplay().getMetrics(mMetrics);
    final int width = getMeasuredWidth();
    final int height = getMeasuredHeight();
    final int newScreenWidth = mMetrics.widthPixels;
    final int newScreenHeight = mMetrics.heightPixels;

    // 移動範囲の設定
    mMoveLimitRect.set(-width, -height * 2, newScreenWidth + width, newScreenHeight + height);
    mPositionLimitRect.set(
        -mOverMargin,
        0,
        newScreenWidth - width + mOverMargin,
        newScreenHeight - mStatusBarHeight - height);

    // 縦横切替の場合
    if (oldScreenWidth != newScreenWidth || oldScreenHeight != newScreenHeight) {
      // 画面端に移動する場合は現在の位置から左右端を設定
      if (mMoveDirection == FloatingViewManager.MOVE_DIRECTION_DEFAULT) {
        // 右半分にある場合
        if (mParams.x > (newScreenWidth - width) / 2) {
          mParams.x = mPositionLimitRect.right;
        }
        // 左半分にある場合
        else {
          mParams.x = mPositionLimitRect.left;
        }
      }
      // 左端に移動
      else if (mMoveDirection == FloatingViewManager.MOVE_DIRECTION_LEFT) {
        mParams.x = mPositionLimitRect.left;
      }
      // 右端に移動
      else if (mMoveDirection == FloatingViewManager.MOVE_DIRECTION_RIGHT) {
        mParams.x = mPositionLimitRect.right;
      }
      // 画面端に移動しない場合は画面座標の比率から計算
      else {
        final int newX =
            (int) (mParams.x * mPositionLimitRect.width() / (float) oldPositionLimitWidth + 0.5f);
        mParams.x = Math.min(Math.max(mPositionLimitRect.left, newX), mPositionLimitRect.right);
      }

      // スクリーン位置の比率からY座標を設定(四捨五入)
      final int newY =
          (int) (mParams.y * mPositionLimitRect.height() / (float) oldPositionLimitHeight + 0.5f);
      mParams.y = Math.min(Math.max(mPositionLimitRect.top, newY), mPositionLimitRect.bottom);
      mWindowManager.updateViewLayout(this, mParams);
    }
  }
예제 #2
0
  /** {@inheritDoc} */
  @Override
  public boolean dispatchTouchEvent(@NonNull MotionEvent event) {
    // Viewが表示されていなければ何もしない
    if (getVisibility() != View.VISIBLE) {
      return true;
    }

    // タッチ不能な場合は何もしない
    if (!mIsDraggable) {
      return true;
    }

    // 現在位置のキャッシュ
    mScreenTouchX = event.getRawX();
    mScreenTouchY = event.getRawY();
    final int action = event.getAction();
    // 押下
    if (action == MotionEvent.ACTION_DOWN) {
      // アニメーションのキャンセル
      cancelAnimation();
      mScreenTouchDownX = mScreenTouchX;
      mScreenTouchDownY = mScreenTouchY;
      mLocalTouchX = event.getX();
      mLocalTouchY = event.getY();
      mIsMoveAccept = false;
      setScale(SCALE_PRESSED);
      // タッチトラッキングアニメーションの開始
      mAnimationHandler.updateTouchPosition(getXByTouch(), getYByTouch());
      mAnimationHandler.removeMessages(FloatingAnimationHandler.ANIMATION_IN_TOUCH);
      mAnimationHandler.sendAnimationMessage(FloatingAnimationHandler.ANIMATION_IN_TOUCH);
      // 長押し判定の開始
      mLongPressHandler.removeMessages(LongPressHandler.LONG_PRESSED);
      mLongPressHandler.sendEmptyMessageDelayed(LongPressHandler.LONG_PRESSED, LONG_PRESS_TIMEOUT);
      // 押下処理の通過判定のための時間保持
      // mIsDraggableやgetVisibility()のフラグが押下後に変更された場合にMOVE等を処理させないようにするため
      mTouchDownTime = event.getDownTime();
    }
    // 移動
    else if (action == MotionEvent.ACTION_MOVE) {
      // 移動判定の場合は長押しの解除
      if (mIsMoveAccept) {
        mIsLongPressed = false;
        mLongPressHandler.removeMessages(LongPressHandler.LONG_PRESSED);
      }
      // 押下処理が行われていない場合は処理しない
      if (mTouchDownTime != event.getDownTime()) {
        return true;
      }
      final float moveThreshold = MOVE_THRESHOLD_DP * mMetrics.density;
      // 移動受付状態でない、かつX,Y軸ともにしきい値よりも小さい場合
      if (!mIsMoveAccept
          && Math.abs(mScreenTouchX - mScreenTouchDownX) < moveThreshold
          && Math.abs(mScreenTouchY - mScreenTouchDownY) < moveThreshold) {
        return true;
      }
      mIsMoveAccept = true;
      mAnimationHandler.updateTouchPosition(getXByTouch(), getYByTouch());
    }
    // 押上、キャンセル
    else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
      // 判定のため長押しの状態を一時的に保持
      final boolean tmpIsLongPressed = mIsLongPressed;
      // 長押しの解除
      mIsLongPressed = false;
      mLongPressHandler.removeMessages(LongPressHandler.LONG_PRESSED);
      // 押下処理が行われていない場合は処理しない
      if (mTouchDownTime != event.getDownTime()) {
        return true;
      }
      // アニメーションの削除
      mAnimationHandler.removeMessages(FloatingAnimationHandler.ANIMATION_IN_TOUCH);
      // 拡大率をもとに戻す
      setScale(SCALE_NORMAL);

      // 動かされていれば画面端に戻す
      if (mIsMoveAccept) {
        moveToEdge(true);
      }
      // 動かされていなければ、クリックイベントを発行
      else {
        if (!tmpIsLongPressed) {
          final int size = getChildCount();
          for (int i = 0; i < size; i++) {
            getChildAt(i).performClick();
          }
        }
      }
    }

    // タッチリスナを通知
    if (mOnTouchListener != null) {
      mOnTouchListener.onTouch(this, event);
    }

    return true;
  }