ScrollView里面基于某個View彈出PopupWindow,PopupWindow不會跟著View滾動?

遇到這樣一個需求:根布局為ScrollView,內部有一個TextView,叫它A,需要在A正上方彈出一個PopupWindow。
初看其實很簡單,根據A的位置和大小,算出PopupWindow的位置,調用showAtLocation方法即可實現在A正上方彈出。
代碼如下:

showPopAlongView(textView);
private void showPopAlongView(View v) {
        View view = View.inflate(this, R.layout.pop_layout, null);
        view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        int measureHeight = view.getMeasuredHeight();
        int measureWidth = view.getMeasuredWidth();
        PopupWindow popupWindow = new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        popupWindow.setFocusable(false);
        popupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
        popupWindow.setOutsideTouchable(false);
        int[] location = new int[2];
        v.getLocationOnScreen(location);
        popupWindow.showAtLocation(v, Gravity.NO_GRAVITY, location[0] + v.getMeasuredWidth() / 2 - measureWidth / 2, location[1] - measureHeight);
    }

如上,就可以在textView正上方顯示出一個PopupWindow。看起來一切都好,但是當ScrollView開始上下滾動的時候,就有問題了:


這里寫圖片描述

可以發現,我們的PopupWindow并沒有跟隨一起滾動,這是因為在調用showAtLocation的時候,PopupWindow的位置已經確定了,所以并不會跟著A的滾動而滾動。
這樣的效果產品經理肯定不會同意的,所以就需要我們來動態更新PopupWindow的位置了。
來看PopupWindow的一個方法:

    /**
     * Updates the position and the dimension of the popup window.
     * <p>
     * Width and height can be set to -1 to update location only. Calling this
     * function also updates the window with the current popup state as
     * described for {@link #update()}.
     *
     * @param x the new x location
     * @param y the new y location
     * @param width the new width in pixels, must be >= 0 or -1 to ignore
     * @param height the new height in pixels, must be >= 0 or -1 to ignore
     */
    public void update(int x, int y, int width, int height) {
        update(x, y, width, height, false);
    }

用這個方法可以更新PopupWindow的尺寸和位置。我們這里只需要讓PopupWindow始終在A的正上方,所以重點就是確定隨著ScrollView的滾動PopupWindow的位置。

  1. 首先定義變量來保存PopupWindow的初始位置和大小
    private int orginalX, originalY;

    private int popWidth, popHeight;
  1. ScrollView設置滾動監聽,計算出PopupWindow新的y坐標,調用update方法更新。
    scrollView.setOnScrollChangeListener(this);
    /**
     * Called when the scroll position of a view changes.
     *
     * @param v          The view whose scroll position has changed.
     * @param scrollX    Current horizontal scroll origin.
     * @param scrollY    Current vertical scroll origin.
     * @param oldScrollX Previous horizontal scroll origin.
     * @param oldScrollY Previous vertical scroll origin.
     */
    @Override
    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
        int currentY = originalY - scrollY;
        popupWindow.update(orginalX, currentY, popWidth, popHeight);
    }

沒錯,步驟就是這么簡單,然后看下效果:

這里寫圖片描述

可以看出,已經基本滿足最開始的需求了。不過好像還有點兒問題,滾動的時候PopupWindow與A之間會有白色空隙,暫時還沒有找到原因,有知道的朋友歡迎留言。

完整代碼地址
選擇moudle:scrollviewwithpopwindow運行即可。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容