我正在研究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
方法移动。