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

男儿欲遂平生志,五经勤向窗前读。这篇文章主要讲述如何在Android屏幕上识别视图移动?相关的知识,希望能为你提供帮助。
我正在开发一个用于制作教程的SDK。在这个SDK中,我提出了一个聚光灯片段,我在其中基本上创建了一个背景画布,我绘制了一个较暗的背景和一个聚焦在所需视??图上的透明矩形。
在某些情况下,此视图可能会移动。例如,使用我的SDK的开发人员在聚焦视图之前创建视图的定时折叠,这使得聚焦视图移动,结果,我的聚光灯保持在错误的位置。
【如何在Android屏幕上识别视图移动()】问题是:如何识别屏幕上的视图移动,以便我可以相应地更新我的聚光灯片段?
答案我现在提出的唯一解决方案是以下“主动”解决方案,我每半秒运行一次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方法。

    推荐阅读