在指定控件位置弹出popup window

先看效果图

黄色的就是弹出的popup window


首先自定义一个view用来显示,文件名为layout_my_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_tips"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textSize="13dp"
android:textColor="#333333"
android:text="。。。"/>

</LinearLayout>

java 代码实现
public class TipsView extends LinearLayout {
    public TipsView(Context context) {
        super(context);
        init();
    }

    public TipsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public TipsView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        inflate(getContext(), R.layout.layout_my_view, this);
    }
}

调用代码

private void showTips() {
        if (mTipsView == null) {
            mTipsView = new TipsView(this);
            mPopupWindow = new PopupWindow(mTipsView, RelativeLayout.LayoutParams.WRAP_CONTENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT, true);
            // 如果不设置PopupWindow的背景,无论是点击外部区域还是Back键都无法dismiss弹框
            mPopupWindow.setBackgroundDrawable(getResources().getDrawable(android.R.color
                    .transparent));
            mPopupWindow.setFocusable(true);
            mPopupWindow.setOutsideTouchable(true);
        }

        if (mPopupWindow.isShowing()) {
            return;
        }

        // 设置好参数之后再show
        int local[] = new int[2];
        //弹出控件的位置,坐标存在local数组
        mTvBindFlag.getLocationOnScreen(local);

        int width = mTipsView.getWidth();
        int height = mTipsView.getHeight();
        if (width == 0 || height == 0) {
            // 获取测量后的宽度
            int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            mTipsView.measure(w, h);
            width = mTipsView.getMeasuredWidth();
            height = mTipsView.getMeasuredHeight();
        }

        // x坐标计算方式:complete_count_txt的x坐标加上他的长度一半(相当于complete_count_txt的横向居中位置)
        // ,再减少弹出气泡宽度的一半(相当于向左移动气泡一半的宽度,就居中显示在complete_count_txt了)
        int x = local[0] + (mTvBindFlag.getWidth() / 2) - width / 2;
        // y坐标计算方式:complete_count_txt的y坐标减去气泡的高度
        int y = local[1] - height;
        // 通过绝对位置显示
       @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
     * @param gravity the gravity which controls the placement of the popup window
     * @param x the popup's x location offset
     * @param y the popup's y location offset
     */
     // public void showAtLocation(View parent, int gravity, int x, int y) 
        mPopupWindow.showAtLocation(mTvBindFlag, Gravity.NO_GRAVITY, x, y);
    }
 
原文地址:https://www.cnblogs.com/lovemo1314/p/5487046.html