如何在Android屏幕上识别视图移动?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Android屏幕上识别视图移动?相关的知识,希望对你有一定的参考价值。
我正在开发一个用于制作教程的SDK。在这个SDK中,我提出了一个聚光灯片段,我在其中基本上创建了一个背景画布,我绘制了一个较暗的背景和一个聚焦在所需视图上的透明矩形。
在某些情况下,此视图可能会移动。例如,使用我的SDK的开发人员在聚焦视图之前创建视图的定时折叠,这使得聚焦视图移动,结果,我的聚光灯保持在错误的位置。
问题是:如何识别屏幕上的视图移动,以便我可以相应地更新我的聚光灯片段?
答案
我现在提出的唯一解决方案是以下“主动”解决方案,我每半秒运行一次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屏幕上识别视图移动?的主要内容,如果未能解决你的问题,请参考以下文章
想要使用片段从导航抽屉活动移动到另一个屏幕,以在所有屏幕上显示抽屉