如何在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屏幕上识别视图移动?的主要内容,如果未能解决你的问题,请参考以下文章

想要使用片段从导航抽屉活动移动到另一个屏幕,以在所有屏幕上显示抽屉

隐藏子屏幕/片段的android底部导航视图

如何在屏幕方向更改时附加片段?

如何在 Xamarin Android 的屏幕上显示全尺寸视图?

Android:如何进行幻灯片视图/布局

片段上的 Mapbox 膨胀视图