PopupWindow简介
PopupWindow是悬浮在当前activity上的一个容器,用它可以展示任意的内容。
PopupWindow跟位置有关的API有下面几个:
- showAsDropDown(View anchor, int xoff, int yoff, int gravity)
显示在anchor的左下角,通过xoff,yoff调整距离,gravity是popup相对于anchor的对齐方式。如果popup超出屏幕,并且展示内容的根容器是滑动控件,将以滑动方式展示。如果展示内容根容器不是滑动控件,超出屏幕内容将不可见。 - showAsDropDown (View anchor, int xoff, int yoff)
同上 - showAsDropDown (View anchor)
同上 - showAtLocation (View parent, int gravity, int x, int y)
展示在屏幕的特定位置,如果内容超出屏幕将被裁剪。
gravity 为NO_GRAVITY等同于 Gravity.LEFT | Gravity.TOP
showAsDropDown 还是showAtLocation?
如果有anchor,可以使用showAsDropDown 方法,如果没有anchor可以使用showAtLocation 方法,注意使用showAtLocation 方法popup内容超出屏幕即使内容放到ScrollView里也不会滚动。
使用Path类自绘制PopupWindow背景
这里选择showAtLocation方法,使用Path类自绘制PopupWindow背景。
绘制规则如下:
给定Popup锚点的x坐标,anchorX;y坐标,anchorYDown,anchorYUp,自定义view会自动计算三角绘制位置,以及显示在anchor下方还是上方。默认显示在下方,下方显示不下再显示在上方。不足是内容太长无法滚动显示。
实现
package com.xxx;
import com.xxx.utils.log.LogUtils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.PathShape;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout.LayoutParams;
import android.widget.PopupWindow;
import android.widget.TextView;
/**
* TextView with popup style background (has triangle on top or bottom). The
* anchor triangle will show accurately below or above the anchor position.
*
* @author wangwenping
* @date 2015-6-27
*/
@SuppressLint("DrawAllocation")
public class PopupTextView extends TextView
{
private static final String TAG = "PopupTextView";
private static final boolean IS_DEBUG = false;
/**
* x of anchor triangle in the popup
*/
private float mTriangleX;
/**
* border color
*/
private int mBorderColor = 0xff1fc38f;
/**
* border width
*/
private int mBorderWidth = 2;
/**
* background color
*/
private int mBgColor = 0xffffffff;
/**
* background color in dark mode
*/
private int mBgColorDark = 0xff999999;
/**
* anchor height
*/
private float mAnchorHeight = 20;
/**
* anchor width
*/
private float mAnchorWidth = 30;
/**
* If content under anchor
*/
private