如何识别Android中屏幕上的移动



我正在研究SDK来制作教程。在此SDK中,我提出了一个聚光灯片段,在该片段中,我基本上创建了一个背景画布,我绘制了一个较暗的背景和一个透明的矩形,重点是所需的视图。

在某些情况下,此视图可能会移动。例如,使用我的SDK的开发人员在集中视图之前创建了视图的定时崩溃,从而使集中的视图移动,结果,我的聚光灯留在错误的位置。

问题是:如何在屏幕上识别一个视图动作,以便我可以相应地更新我的聚光灯片段?

我现在提出的唯一解决方案是以下'Active'解决方案,我每半秒钟运行Task,检查目标视图的LocationOnScreen。如果目标视图更改,则它的坐标,我会更新片段。该解决方案有效,但我仍在寻找一种"被动"解决方案,该解决方案在位置上更新我,而不是每半秒进行一次测试:

  @Override
public void onStart() {
    super.onStart();
    final View targetView = mDrawDataPojo.getWalkthroughMetaPojo().getTargetView().getView();
    if (targetView != null) {
        targetView.getLocationOnScreen(mOriginalLocationOnScreen);
        mTimer = new Timer();
        mTimer.schedule(new TargetViewChangeListener(), 0, 500);
    }
    ...
}
@Override
public void onPause() {
    super.onPause();
    if (mTimer != null) {
        mTimer.cancel();
    }
    ...
}
 class TargetViewChangeListener extends TimerTask {
    public void run() {
        int[] currentLocation = new int[2];
        mDrawDataPojo.getWalkthroughMetaPojo().getTargetView().getView().getLocationOnScreen(currentLocation);
        if (currentLocation[0] != mOriginalLocationOnScreen[0] || currentLocation[1] != mOriginalLocationOnScreen[1]) {
            final boolean isActionBar = ABUtils.isActionBarActivity(getActivity());
            final int containerId;
            try {
                mDrawDataPojo.getWalkthroughMetaPojo().setTargetView(new SpotlightTargetView(getActivity(), mDrawDataPojo.getWalkthroughMetaPojo().getTargetView().getView()));
                containerId = AndroidUtils.getContainerId(getActivity(), isActionBar);
                ABPromotionFragment abPromotionFragment = ABPromotionFragment.newInstance(mDrawDataPojo.getViewDataPojo(), null, mDrawDataPojo.getWalkthroughMetaPojo());
                FragmentManager fragmentManager = getActivity().getFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
                        .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
                fragmentTransaction.replace(containerId, abPromotionFragment);
                fragmentTransaction.commitAllowingStateLoss();
            } catch (Exception e) {
                ABLogger.d("TargetViewChangeListener - TimerTask - exception: " + e);
            }
        }
    }
}

使用OnPreDrawListener找到了更好的解决方案:

private final ViewTreeObserver.OnPreDrawListener mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            if (!mAttached) {
                removePreDrawObserver(null);
                return true;
            }
            handleViewDraw();
            return true;
        }
    };

每当视图重新绘制时,onPreDraw方法都会被调用。

handleViewDraw方法将看起来像以下内容:

private void handleViewDraw() {
        if (if mViewAnchor != null) {
            View view = mViewAnchor.get();
            if (null != view && view.getVisibility() == VISIBLE) {
                view.getLocationOnScreen(mTempLocation);
                if (mOldLocation == null) {
                    mOldLocation = new int[]{mTempLocation[0], mTempLocation[1]};
                }
                if (isTargetViewLocationChanged()) {
                    handleVisibleTargetViewLocationChange();
                }
                mOldLocation[0] = mTempLocation[0];
                mOldLocation[1] = mTempLocation[1];
            } else {
                mView.setVisibility(INVISIBLE);
            }
        } else {
            mView.setVisibility(INVISIBLE);
        }
    }
private boolean isTargetViewLocationChanged() {
        Log.d(TAG, "Old: " + mOldLocation[1] + " ,TEMP: " + mTempLocation[1]);
        return mOldLocation[0] != mTempLocation[0] || mOldLocation[1] != mTempLocation[1];
    }

使用此方法,只有在视图移动时才通知您,与其他答案中提供的"活动"解决方案不同,这是一种"被动"解决方案,仅当视图实际上具有实际上才能运行handleVisibleTargetViewLocationChange方法移动。

最新更新