男儿欲遂平生志,五经勤向窗前读。这篇文章主要讲述如何在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
方法。推荐阅读
- Android View和ViewGroup
- 无法在Asynctask Android,java中调用View
- 调用ondraw后重置画布,然后再在android中调用它
- 在Android应用中正确加载资源(使用openGL)
- 是否有适用于Android的图像编辑SDK [关闭]
- 如何在Android中的Canvas上移动路径()
- 查找JApplet的宽度和高度
- 使用AppActivate更改活动窗口
- 以编程方式测试是否在Android 10+中禁用了旧版外部存储访问