如何在Android屏幕上识别视图移动?

时间:2017-06-29 15:07:42

标签: android android-fragments view

我正在开发SDK来制作教程。在这个SDK中,我提出了一个聚光灯片段,我在其中基本上创建了一个背景画布,我绘制了一个较暗的背景和一个聚焦在所需视​​图上的透明矩形。

在某些情况下,此观点可能会移动。例如,使用我的SDK的开发人员在聚焦视图之前创建视图的定时折叠,这使得聚焦视图移动,结果,我的聚光灯停留在错误的位置。

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

2 个答案:

答案 0 :(得分:1)

我现在提出的唯一解决方案是以下“主动”解决方案,我每隔半秒运行一次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);
            }
        }
    }
}

答案 1 :(得分:0)

使用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方法时视图实际上已经移动了。