弹窗自定义尖角,先看下效果图。
删除按钮的位置不确定,还要根据按钮位置来确定弹窗实在按钮上方还是下方展示,尖角有可能在左边,也可能在右边或者中间。(为什么自定义呢?UI不会切点9。。。。)代码
public class CornerPopupWindow extends PopupWindow {
private CornerRelativeLayout cornerView;
private Context context;
public CornerPopupWindow(Context context) {
this.context = context;
setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
setFocusable(true);
setOutsideTouchable(false);
setClippingEnabled(false);
}
public void setCornerView(View view) {//弹窗内布局
cornerView = new CornerRelativeLayout(context);
cornerView.setBackgroundColor(Color.TRANSPARENT);
cornerView.addView(view);
setContentView(cornerView);
}
/**
* 显示弹窗
*/
public void show(View view) {//view为删除点击的按钮
CornerRelativeLayout.CornerLegOrientation orientation = null;
final int anchorLoc[] = new int[2];
final int windowPos[] = new int[2];
// 获取锚点View在屏幕上的左上角坐标位置
view.getLocationOnScreen(anchorLoc);
final int anchorHeight = view.getHeight();
// 获取屏幕的高宽
final int screenHeight = PublicViewUtils.getDisplayHeight(view.getContext());
final int screenWidth = PublicViewUtils.getDisplayWidth(view.getContext());
// 测量contentView
cornerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
// 计算contentView的高宽
final int windowHeight = cornerView.getMeasuredHeight();
final int windowWidth = cornerView.getMeasuredWidth();
// 判断需要向上弹出还是向下弹出显示
final boolean isNeedShowUp = (screenHeight - anchorLoc[1] - anchorHeight < windowHeight);
if (isNeedShowUp) {
windowPos[0] = screenWidth - windowWidth;
windowPos[1] = anchorLoc[1] - windowHeight;
orientation = CornerRelativeLayout.CornerLegOrientation.BOTTOM;
} else {
windowPos[0] = screenWidth - windowWidth;
windowPos[1] = anchorLoc[1] + anchorHeight;
orientation = CornerRelativeLayout.CornerLegOrientation.TOP;
}
if (!this.isShowing()) {
cornerView.setCornerParams(anchorLoc[0] + view.getWidth()/2, orientation, 0.75f); // 设置气泡布局方向及尖角偏移
showAtLocation(view, Gravity.TOP | Gravity.START, 0, windowPos[1]);
} else {
this.dismiss();
}
}
}
尖角(只添加了上下,左右可以在renderCornerLegMatrix添加)
public class CornerRelativeLayout extends RelativeLayout {
public enum CornerLegOrientation {
TOP, BOTTOM
}
public int PADDING = 30;
public float STROKE_WIDTH = 2.0f;
public float CORNER_RADIUS = 8.0f;
public int SHADOW_COLOR = Color.argb(100, 0, 0, 0);
private Paint mFillPaint = null;
private final Path mPath = new Path();
private final Path mCornerPath = new Path();
private final Paint mPaint = new Paint(Paint.DITHER_FLAG);
private float mCornerLegOffset = 0.75f;
private CornerLegOrientation mCornerLegOrientation = CornerLegOrientation.TOP;
private int xLocation;
public CornerRelativeLayout(Context context) {
this(context, null);
}
public CornerRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CornerRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(final Context context, final AttributeSet attrs) {
//setGravity(Gravity.CENTER);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
setLayoutParams(params);
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.corner);
try {
PADDING = a.getDimensionPixelSize(R.styleable.corner_padding, PADDING);
SHADOW_COLOR = a.getInt(R.styleable.corner_shadowColor, SHADOW_COLOR);
STROKE_WIDTH = a.getFloat(R.styleable.corner_buStrokeWidth, STROKE_WIDTH);
CORNER_RADIUS = a.getFloat(R.styleable.corner_buCornerRadius, CORNER_RADIUS);
} finally {
if (a != null) {
a.recycle();
}
}
}
mPaint.setColor(SHADOW_COLOR);
mPaint.setStyle(Style.FILL);
mPaint.setStrokeCap(Cap.BUTT);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(STROKE_WIDTH);
mPaint.setStrokeJoin(Paint.Join.MITER);
mPaint.setPathEffect(new CornerPathEffect(CORNER_RADIUS));
if (Build.VERSION.SDK_INT >= 11) {
setLayerType(LAYER_TYPE_SOFTWARE, mPaint);
}
mFillPaint = new Paint(mPaint);
mFillPaint.setColor(Color.WHITE);
mFillPaint.setShader(new LinearGradient(100f, 0f, 100f, 200f, Color.WHITE, Color.WHITE, TileMode.CLAMP));
if (Build.VERSION.SDK_INT >= 11) {
setLayerType(LAYER_TYPE_SOFTWARE, mFillPaint);
}
mPaint.setShadowLayer(2f, 2F, 5F, SHADOW_COLOR);
renderCornerLegPrototype();
setPadding(PADDING, PADDING, PADDING, PADDING);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
/**
* 尖角path
*/
private void renderCornerLegPrototype() {
mCornerPath.moveTo(0, 0);
mCornerPath.lineTo(PADDING * 1.5f, -PADDING / 1.5f);
mCornerPath.lineTo(PADDING * 1.5f, PADDING / 1.5f);
mCornerPath.close();
}
public void setCornerParams(int xLocation, final CornerLegOrientation cornerLegOrientation, final float cornerOffset) {
this.xLocation = xLocation;
mCornerLegOffset = cornerOffset;
this.mCornerLegOrientation = cornerLegOrientation;
}
/**
* 根据显示方向,获取尖角位置矩阵
* @param width
* @param height
* @return
*/
private Matrix renderCornerLegMatrix(final float width, final float height) {
float dstX = 0;
float dstY = 0;
final Matrix matrix = new Matrix();
switch (mCornerLegOrientation) {
case TOP:
dstX = xLocation;
dstY = 0;
matrix.postRotate(90);
break;
case BOTTOM:
dstY = height;
dstX = xLocation;
matrix.postRotate(270);
break;
}
matrix.postTranslate(dstX, dstY);
return matrix;
}
@Override
protected void onDraw(Canvas canvas) {
final float width = canvas.getWidth();
final float height = canvas.getHeight();
mPath.rewind();
mPath.addRoundRect(new RectF(PADDING, PADDING, width - PADDING, height - PADDING), CORNER_RADIUS, CORNER_RADIUS, Direction.CW);//画圆角举行
mPath.addPath(mCornerPath, renderCornerLegMatrix(width, height));//添加尖角
canvas.drawPath(mPath, mPaint);
canvas.scale((width - STROKE_WIDTH) / width, (height - STROKE_WIDTH) / height, width / 2f, height / 2f);
canvas.drawPath(mPath, mFillPaint);
}
}
使用:
CornerPopupWindow mPopupWindow = new CornerPopupWindow(context);
mPopupWindow.setCornerView(view);
PublicViewUtils.backgroundAlpha(context, 0.4f);
mPopupWindow.show(按钮);