今天我接着站在了巨人的肩膀上了!由于上次我参考大神利用 Path 实现了点九图效果,附上我上次讲解连接: juejin.im/post/58c3b8… .这一次,我将完成上次说的实现点击toolbar按钮弹出菜单效果,固然仍是利用 Path 来完成这个效果.若是想看巨人的巨做,请点击: juejin.im/post/5865f4… ,我这次仅仅是将大神的点九图更换为一个由Path完成的效果而已.javascript
首先,咱们仍是看下我完成的结果吧!java
嘿嘿,和大神的同样哈!是的,我只是改了背景图而已.这样咱们就能够随便刷不要UI哥帮忙了,并且那个三角凸起能够 左右位置调整 哦!android
首先仍是看下MainActivity的布局吧git
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.jooyerbubblemenu.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/colorPrimary">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="@string/app_name"
android:textColor="@android:color/white"
android:textSize="20sp"
android:layout_centerVertical="true"/>
<ImageView
android:id="@+id/more"
android:layout_width="50dp"
android:layout_height="match_parent"
android:src="@mipmap/common_forward_normal"
android:scaleType="center"
android:layout_alignParentRight="true"/>
</RelativeLayout>
</LinearLayout>复制代码
这个就不说啥了,接着,来重点了,看 Recyclerview 了,由于大神用的是这个控件,那我只是给这个控件换了个衣服!github
package com.jooyerbubblemenu;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
/** * Created by Jooyer on 2017/3/19 */
public class JooyerBubbleRecyclerView extends RecyclerView{
private JooyerBubbleDrawable mBubbleDrawable;
private float mArrowWidth;
private float mArrowHeight;
private float mRadius;
private float mArrowOffset;
private int mBubbleColor;
private JooyerBubbleDrawable.ArrowDirection mArrowDirection;
private boolean mArrowCenter;
public JooyerBubbleRecyclerView(Context context) {
this(context,null);
}
public JooyerBubbleRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public JooyerBubbleRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context,attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(R.styleable.JooyerBubbleRecyclerView);
mArrowWidth = array.getDimension(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_width,
JooyerBubbleDrawable.Builder.DEFAULT_ARROW_WIDTH);
mArrowHeight = array.getDimension(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_height,
JooyerBubbleDrawable.Builder.DEFAULT_ARROW_HEIGHT);
mRadius = array.getDimension(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_radius,
JooyerBubbleDrawable.Builder.DEFAULT_RADIUS);
int location = array.getInt(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_direction, 0);
mArrowDirection = JooyerBubbleDrawable.ArrowDirection.mapIntToValue(location);
mArrowOffset = array.getDimension(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_offset,
JooyerBubbleDrawable.Builder.DEFAULT_ARROW_OFFSET);
mBubbleColor = array.getColor(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_color,
JooyerBubbleDrawable.Builder.DEFAULT_BUBBLE_COLOR);
mArrowCenter = array.getBoolean(R.styleable.JooyerBubbleRecyclerView_jooyer_bubble_arrow_center,false);
array.recycle();
setPadding();
}
private void setPadding() {
int left = getPaddingLeft();
int top = getPaddingTop();
int right = getPaddingRight();
int bottom = getPaddingBottom();
switch (mArrowDirection){
case LEFT:
left +=mArrowWidth;
break;
case TOP:
top += mArrowHeight;
break;
case RIGHT:
right += mArrowWidth;
break;
case BOTTOM:
bottom +=mArrowHeight;
break;
}
setPadding(left,top,right,bottom);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w >0 || h > 0)
setUp(w,h);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
setUp(getWidth(),getHeight());
}
@Override
public void onDraw(Canvas c) {
if (null != mBubbleDrawable){
mBubbleDrawable.draw(c);
}
super.onDraw(c);
}
private void setUp(int width,int height){
setUp(0,0,width,height);
}
public void setUp(int left,int top,int right,int bottom){
mBubbleDrawable = new JooyerBubbleDrawable.Builder()
.rect(new RectF(left,top,right,bottom))
.arrowWidth(mArrowWidth)
.arrowHeight(mArrowHeight)
.arrowOffset(mArrowOffset)
.arrowCenter(mArrowCenter)
.arrowDirection(mArrowDirection)
.radius(mRadius)
.bubbleColor(mBubbleColor)
.build();
}
public void setArrowOffset(float offset){
mArrowOffset = offset;
}
}复制代码
没有什么注释,起始和上一篇文章自定义同样的,因此咱们主要就是熟悉这种方式而已!
咱们仍是瞅一眼 JooyerBubbleDrawable canvas
package com.jooyerbubblemenu;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.Log;
/** * Created by Jooyer on 2017/3/11 */
public class JooyerBubbleDrawable extends Drawable {
private static final String TAG = JooyerBubbleDrawable.class.getSimpleName();
/** * 保存坐标(自定义控件的大小) */
private RectF mRect;
/** * 气泡的路径 */
private Path mPath = new Path();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
/** * 箭头宽度 */
private float mArrowWidth;
/** * 箭头宽度 */
private float mArrowHeight;
/** * 圆弧半径 */
private float mRadius;
/** * 箭头所在位置偏移量 */
private float mArrowOffset;
/** * 气泡背景色 */
private int mBubbleColor;
/** * 三角箭头所在位置 */
private ArrowDirection mArrowDirection;
/** * 箭头是否居中 */
private boolean mArrowCenter;
/** * 重写此方法,在这里实现和 自定义控件中 onDraw 相似的功能 */
@Override
public void draw(Canvas canvas) {
mPaint.setColor(mBubbleColor);
setUpPath(mArrowDirection, mPath);
canvas.drawPath(mPath, mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT; //窗口透明化
}
private void setUpPath(ArrowDirection arrowDirection, Path path) {
switch (arrowDirection) {
case LEFT:
setUpLeftPath(mRect, path);
break;
case TOP:
setUpTopPath(mRect, path);
break;
case RIGHT:
setUpRightPath(mRect, path);
break;
case BOTTOM:
setUpBottomPath(mRect,path);
break;
}
}
/** * 箭头朝左 */
private void setUpLeftPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.bottom - rect.top - mArrowWidth) / 2;
path.moveTo(rect.left + mArrowWidth + mRadius, rect.top);
path.lineTo(rect.width() - mRadius, rect.top); // 这里的rect.width() 是能够使用rect.right
Log.i(TAG, "====setUpLeftPath========" + (rect.width() - mRadius) + "======= : " + (rect.right - mRadius));
path.arcTo(new RectF(rect.right - mRadius, rect.top, rect.right, rect.top + mRadius), 270, 90);
path.lineTo(rect.right, rect.bottom - mRadius);
path.arcTo(new RectF(rect.right - mRadius, mRect.bottom - mRadius, rect.right, rect.bottom), 0, 90);
path.lineTo(rect.left + mArrowWidth + mRadius, rect.bottom);
path.arcTo(new RectF(rect.left + mArrowWidth, rect.bottom - mRadius, rect.left + mArrowWidth + mRadius, rect.bottom), 90, 90);
path.lineTo(rect.left + mArrowWidth, mArrowHeight + mArrowOffset);
path.lineTo(rect.left, mArrowOffset + mArrowHeight / 2);
path.lineTo(rect.left + mArrowWidth, mArrowOffset);
path.lineTo(rect.left + mArrowWidth, rect.top + mRadius);
path.arcTo(new RectF(rect.left + mArrowWidth, mRect.top, rect.left + mArrowWidth + mRadius, rect.top + mRadius), 180, 90);
path.close();
}
/** * 箭头朝上 */
private void setUpTopPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.right - rect.left - mArrowWidth) / 2;
path.moveTo(rect.left + Math.min(mRadius, mArrowOffset), rect.top + mArrowHeight);
path.lineTo(rect.left + mArrowOffset, rect.top + mArrowHeight);
path.lineTo(rect.left + mArrowOffset + mArrowWidth / 2, rect.top);
path.lineTo(rect.left + mArrowOffset + mArrowWidth, rect.top + mArrowHeight);
path.lineTo(rect.right - mRadius, rect.top + mArrowHeight);
path.arcTo(new RectF(rect.right - mRadius, rect.top + mArrowHeight, rect.right, rect.top + mArrowHeight + mRadius), 270, 90);
path.lineTo(rect.right, rect.bottom - mRadius);
path.arcTo(new RectF(rect.right - mRadius, rect.bottom - mRadius, rect.right, rect.bottom), 0, 90);
path.lineTo(rect.left + mRadius, rect.bottom);
path.arcTo(new RectF(rect.left, rect.bottom - mRadius, rect.left + mRadius, rect.bottom), 90, 90);
path.lineTo(rect.left, rect.top + mArrowHeight + mRadius);
path.arcTo(new RectF(rect.left, rect.top + mArrowHeight, rect.left + mRadius, rect.top + mArrowHeight + mRadius), 180, 90);
path.close();
}
/** * 箭头朝右 */
private void setUpRightPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.bottom - rect.top - mArrowWidth) / 2;
path.moveTo(rect.left + mRadius, rect.top);
path.lineTo(rect.right - mRadius - mArrowWidth, rect.top);
path.arcTo(new RectF(rect.right - mArrowWidth - mRadius, rect.top, rect.right - mArrowWidth, rect.top + mRadius), 270, 90);
path.lineTo(rect.right - mArrowWidth, rect.top + mArrowOffset);
path.lineTo(rect.right, rect.top + mArrowOffset + mArrowHeight / 2);
path.lineTo(rect.right - mArrowWidth, rect.top + mArrowOffset + mArrowHeight);
path.lineTo(rect.right - mArrowWidth, rect.bottom - mRadius);
path.arcTo(new RectF(rect.right - mArrowWidth - mRadius, rect.bottom - mRadius, rect.right - mArrowWidth, rect.bottom), 0, 90);
path.lineTo(rect.right - mArrowWidth - mRadius, rect.bottom);
path.arcTo(new RectF(rect.left, rect.bottom - mRadius, rect.left + mRadius, rect.bottom), 90, 90);
path.lineTo(rect.left, rect.top + mRadius);
path.arcTo(new RectF(rect.left, rect.top, rect.left + mRadius, rect.top + mRadius), 180, 90);
path.close();
}
/** * 箭头朝下 */
private void setUpBottomPath(RectF rect, Path path) {
if (mArrowCenter)
mArrowOffset = (rect.right - rect.left - mArrowWidth) / 2;
path.moveTo(rect.left + mRadius, rect.top);
path.lineTo(rect.right - mRadius, rect.top);
path.arcTo(new RectF(rect.right - mRadius, rect.top, rect.right, rect.top + mRadius), 270, 90);
path.lineTo(rect.right, rect.bottom - mArrowHeight - mRadius);
path.arcTo(new RectF(rect.right - mRadius, rect.bottom - mArrowHeight - mRadius, rect.right, rect.bottom - mArrowHeight), 0, 90);
path.lineTo(rect.left + mArrowOffset + mArrowWidth, rect.bottom - mArrowHeight);
path.lineTo(rect.left + mArrowOffset + mArrowWidth / 2, rect.bottom);
path.lineTo(rect.left + mArrowOffset, rect.bottom - mArrowHeight);
path.lineTo(rect.left + mRadius, rect.bottom - mArrowHeight);
path.arcTo(new RectF(rect.left, rect.bottom - mArrowHeight - mRadius, rect.left + mRadius, rect.bottom - mArrowHeight), 90, 90);
path.lineTo(rect.left, rect.top + mRadius);
path.arcTo(new RectF(rect.left, rect.top,rect.left + mRadius,rect.top + mRadius),180,90);
path.close();
}
private JooyerBubbleDrawable(Builder builder) {
this.mRect = builder.mRectF;
this.mRadius = builder.mRadius;
this.mArrowWidth = builder.mArrowWidth;
this.mArrowHeight = builder.mArrowHeight;
this.mArrowOffset = builder.mArrowOffset;
this.mBubbleColor = builder.mBubbleColor;
this.mArrowDirection = builder.mArrowDirection;
this.mArrowCenter = builder.mArrowCenter;
}
/** * 建造者模式 */
public static class Builder {
/** * 箭头默认宽度 */
public static float DEFAULT_ARROW_WIDTH = 25;
/** * 箭头默认高度 */
public static float DEFAULT_ARROW_HEIGHT = 25;
/** * 默认圆角半径 */
public static float DEFAULT_RADIUS = 20;
/** * 默认箭头偏移量 */
public static float DEFAULT_ARROW_OFFSET = 50;
/** * 气泡默认背景颜色 */
public static int DEFAULT_BUBBLE_COLOR = Color.RED;
private RectF mRectF;
private float mArrowWidth = DEFAULT_ARROW_WIDTH;
private float mArrowHeight = DEFAULT_ARROW_HEIGHT;
private float mRadius = DEFAULT_RADIUS;
private float mArrowOffset = DEFAULT_ARROW_OFFSET;
private int mBubbleColor = DEFAULT_BUBBLE_COLOR;
private ArrowDirection mArrowDirection = ArrowDirection.LEFT;
private boolean mArrowCenter;
public Builder rect(RectF rect) {
this.mRectF = rect;
return this;
}
public Builder arrowWidth(float width) {
this.mArrowWidth = width;
return this;
}
public Builder arrowHeight(float height) {
this.mArrowHeight = height;
return this;
}
public Builder radius(float angle) {
this.mRadius = angle; //TODO
return this;
}
public Builder arrowOffset(float position) {
this.mArrowOffset = position;
return this;
}
public Builder bubbleColor(int color) {
this.mBubbleColor = color;
return this;
}
public Builder arrowDirection(ArrowDirection direction) {
this.mArrowDirection = direction;
return this;
}
public Builder arrowCenter(boolean arrowCenter) {
this.mArrowCenter = arrowCenter;
return this;
}
public JooyerBubbleDrawable build() {
if (null == mRectF) {
throw new IllegalArgumentException("BubbleDrawable RectF can not be null");
}
return new JooyerBubbleDrawable(this);
}
}
/** * 箭头位置 */
public enum ArrowDirection {
LEFT(0x00),
TOP(0x01),
RIGHT(0x02),
BOTTOM(0x03);
private int mValue;
ArrowDirection(int value) {
mValue = value;
}
private int getIntValue() {
return mValue;
}
public static ArrowDirection getDefault() {
return LEFT;
}
public static ArrowDirection mapIntToValue(int stateInt) {
for (ArrowDirection value : ArrowDirection.values()) {
if (stateInt == value.getIntValue()) {
return value;
}
}
return getDefault();
}
}
}复制代码
自定义属性app
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="JooyerBubbleRecyclerView">
<!-- 三角箭头宽度 -->
<attr name="jooyer_bubble_arrow_width" format="dimension"/>
<!-- 三角箭头高度 -->
<attr name="jooyer_bubble_arrow_height" format="dimension"/>
<!-- 三角箭头位置(相对偏移量) -->
<attr name="jooyer_bubble_arrow_offset" format="dimension"/>
<!-- 气泡圆角半径 -->
<attr name="jooyer_bubble_arrow_radius" format="dimension"/>
<!-- 气泡背景颜色 -->
<attr name="jooyer_bubble_arrow_color" format="color"/>
<!-- 三角箭头是否居中 -->
<attr name="jooyer_bubble_arrow_center" format="boolean"/>
<!-- 三角箭头方向朝向 -->
<attr name="jooyer_bubble_arrow_direction" format="enum">
<enum name="jooyer_bubble_arrow_direction_left" value="0x00"/>
<enum name="jooyer_bubble_arrow_direction_top" value="0x01"/>
<enum name="jooyer_bubble_arrow_direction_right" value="0x02"/>
<enum name="jooyer_bubble_arrow_direction_bottom" value="0x03"/>
</attr>
</declare-styleable>
</resources>复制代码
咱们看下它的具体用法:ide
<?xml version="1.0" encoding="utf-8"?>
<com.jooyerbubblemenu.JooyerBubbleRecyclerView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:toools="http://schemas.android.com/tools" android:id="@+id/rv_top_right_menu" android:layout_width="match_parent" android:layout_height="match_parent" app:jooyer_bubble_arrow_width="8dp" app:jooyer_bubble_arrow_height="10dp" app:jooyer_bubble_arrow_offset="20dp" app:jooyer_bubble_arrow_radius="10dp" app:jooyer_bubble_arrow_center="false" app:jooyer_bubble_arrow_color="#fff" app:jooyer_bubble_arrow_direction="jooyer_bubble_arrow_direction_top" toools:itemlist="@layout/top_right_menu_item" />复制代码
接下来,咱们看看大神封装的Item和PopupWindow布局
package com.jooyerbubblemenu;
/** * 每一项菜单 * Created by Jooyer on 2017/2/10 */
public class MenuItem {
private int icon;
private String content;
public MenuItem() {
}
public MenuItem(int icon, String content) {
this.icon = icon;
this.content = content;
}
public int getIcon() {
return icon;
}
public void setIcon(int icon) {
this.icon = icon;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}复制代码
大神的神剑: TopRightMenupost
package com.jooyerbubblemenu;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.PopupWindow;
import com.jooyerbubblemenu.utils.LogUtils;
import java.util.ArrayList;
import java.util.List;
/** * 封装一个PopupWindow 实现相似QQ,支付宝等右上角弹框效果 * Created by Jooyer on 2017/2/10 */
public class TopRightMenu {
private static final String TAG = "TopRightMenu";
private static final int DEFAULT_AMEND = 200;
private Context mContext;
private PopupWindow mPopupWindow;
private RecyclerView mRecyclerView;
private View mParent;
private TopRightMenuAdapter mTopRightMenuAdapter;
private List<MenuItem> mItemList;
/** * 弹窗默认高度 */
private static final int DEFAULT_HEIGHT = 480;
/** * 弹窗默认高度 */
private static final int DEFAULT_WIDTH = 320;
private int mPopupHeight = DEFAULT_HEIGHT;
private int mPopupWidth = DEFAULT_WIDTH;
/** * 默认显示图标 */
private boolean isShowIcon = true;
/** * 默认显示背景 --> 背景变暗 */
private boolean isShowBackground = true;
/** * 默认显示动画 */
private boolean isShowAnimationStyle = true;
/** * 默认弹出或者关闭动画 */
private static final int DEFAULT_ANIM_STYLE = R.style.TopRightMenu_Anim;
private int mAnimationStyle;
/** * 默认的透明度值 */
private float mAlpha = 0.7f;
public TopRightMenu(Context context) {
mContext = context;
init();
}
private void init() {
mParent = LayoutInflater.from(mContext).inflate(R.layout.top_right_menu, null);
mRecyclerView = (RecyclerView) mParent.findViewById(R.id.rv_top_right_menu);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
mRecyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
mItemList = new ArrayList<>();
mTopRightMenuAdapter = new TopRightMenuAdapter(mContext, mItemList, isShowIcon, this);
}
/** * 设置高度 */
public TopRightMenu setHeight(int height) {
if (height > 0) {
this.mPopupHeight = height;
}
return this;
}
/** * 设置宽度 */
public TopRightMenu setWidth(int width) {
if (width > 0) {
this.mPopupWidth = width;
} else {
throw new IllegalArgumentException("宽度不能为空,且必须大于0!");
}
return this;
}
/** * 设置是否显示图标 */
public TopRightMenu setShowIcon(boolean isShowIcon) {
this.isShowIcon = isShowIcon;
return this;
}
/** * 设置背景是否变暗 */
public TopRightMenu setShowBackground(boolean isShowBackground) {
this.isShowBackground = isShowBackground;
return this;
}
/** * 设置背景颜色变化动画 * * @param from --> 开始值 * @param to --> 结束值 * @param duration --> 持续时间 */
private void setBackgroundAlpha(float from, float to, int duration) {
final WindowManager.LayoutParams lp = ((Activity) mContext).getWindow().getAttributes();
ValueAnimator animator = ValueAnimator.ofFloat(from, to);
animator.setDuration(duration);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
lp.alpha = (float) animation.getAnimatedValue();
((Activity) mContext).getWindow().setAttributes(lp);
}
});
animator.start();
}
/** * 设置是否显示动画 */
public TopRightMenu setShowAnimationStyle(boolean isShowAnimationStyle) {
this.isShowAnimationStyle = isShowAnimationStyle;
return this;
}
/** * 设置动画 */
public TopRightMenu setAnimationStyle(int animationStyle) {
this.mAnimationStyle = animationStyle;
return this;
}
/** * 添加单个菜单 */
public TopRightMenu addMenuItem(MenuItem menuItem) {
mItemList.add(menuItem);
return this;
}
/** * 添加多个菜单 */
public TopRightMenu addMenuItems(List<MenuItem> list) {
mItemList.addAll(list);
return this;
}
public TopRightMenu setOnTopRightMenuItemClickListener(OnTopRightMenuItemClickListener listener) {
mTopRightMenuAdapter.setOnTopRightMenuItemClickListener(listener);
return this;
}
public TopRightMenu showAsDropDown(View anchor) {
showAsDropDown(anchor, 0, 0);
return this;
}
public TopRightMenu setArrowPosition(float value) {
if (mRecyclerView != null && mRecyclerView instanceof JooyerBubbleRecyclerView) {
((JooyerBubbleRecyclerView) mRecyclerView).setArrowOffset(value);
}
return this;
}
public TopRightMenu showAsDropDown(View anchor, int offsetX, int offsetY) {
if (null == mPopupWindow) {
mPopupWindow = getPopupWindow();
}
if (!mPopupWindow.isShowing()) {
mPopupWindow.showAsDropDown(anchor, offsetX, offsetY);
if (isShowBackground)
setBackgroundAlpha(1f, mAlpha, 300);
}
return this;
}
public TopRightMenu show(View anchor, Rect frame, Point origin) {
if (null == mPopupWindow) {
mPopupWindow = getPopupWindow();
}
if (null == frame) frame = new Rect();
if (null == origin) origin = new Point(-1, -1);
int[] location = reviseFrameAndOrigin(anchor, frame, origin);
int x = location[0];
int y = location[1];
LogUtils.i(TAG, "==location====X : " + x + "======Y : " + y);
int width = anchor.getWidth();
int height = anchor.getHeight();
int contentHeight = mPopupWindow.getContentView().getMeasuredHeight();
if (!mPopupWindow.isShowing()) {
if (y + height + contentHeight < frame.bottom) {
mPopupWindow.showAsDropDown(anchor, (int) (-DEFAULT_AMEND - (mPopupWidth - DEFAULT_WIDTH)), 0);
LogUtils.i(TAG, "=====showAsDropDown=====" + (int) (-DEFAULT_AMEND - (mPopupWidth - DEFAULT_WIDTH)));
}
if (isShowBackground)
setBackgroundAlpha(1f, mAlpha, 300);
}
return this;
}
/** * 肯定 弹框的位置 */
private int[] reviseFrameAndOrigin(View anchor, Rect frame, Point origin) {
int[] location = new int[2];
anchor.getLocationInWindow(location);
if (origin.x < 0 || origin.y < 0) {
origin.set(anchor.getWidth() >> 1, anchor.getHeight() >> 1);
LogUtils.i(TAG, "====1====" + (anchor.getWidth() >> 1) + "=====" + (anchor.getHeight() >> 1)
+ "=======getWidth : " + anchor.getWidth() + "===== : " + anchor.getHeight());
}
if (frame.isEmpty() || !frame.contains(origin.x + location[0], origin.y + location[1])) {
anchor.getWindowVisibleDisplayFrame(frame);
}
LogUtils.i(TAG, "====2====" + (origin.x + location[0]) + "=====" + (origin.y + location[1]));
return location;
}
private PopupWindow getPopupWindow() {
mPopupWindow = new PopupWindow(mContext);
mPopupWindow.setContentView(mParent);
mPopupWindow.setWidth(mPopupWidth);
mPopupWindow.setHeight(mPopupHeight);
if (isShowAnimationStyle)
mPopupWindow.setAnimationStyle(mAnimationStyle <= 0 ? DEFAULT_ANIM_STYLE : mAnimationStyle);
mPopupWindow.setFocusable(true);
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setBackgroundDrawable(new ColorDrawable());
mPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if (isShowBackground)
setBackgroundAlpha(mAlpha, 1f, 300);
}
});
mTopRightMenuAdapter.setItemData(mItemList);
mTopRightMenuAdapter.setShowIcon(isShowIcon);
mRecyclerView.setAdapter(mTopRightMenuAdapter);
return mPopupWindow;
}
public void dismiss() {
if (null != mPopupWindow && mPopupWindow.isShowing())
mPopupWindow.dismiss();
}
}复制代码
以上我在不明白的地方打印有日志输入,能够了解大神用意
最后来看哈使用方式:
package com.jooyerbubblemenu;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ImageView more;
private TopRightMenu mTopRightMenu;
private List<MenuItem> mItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initMenu();
more = (ImageView) findViewById(R.id.more);
mTopRightMenu = new TopRightMenu(this);
more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTopRightMenu.setWidth(400)
.setHeight(600)
.setShowIcon(true)
.setShowAnimationStyle(true)
.setAnimationStyle(R.style.TopRightMenu_Anim)
.setShowBackground(true)
.setArrowPosition(345f)
.addMenuItems(mItems)
.addMenuItem(new MenuItem(R.mipmap.facetoface,"面对面快传"))
.addMenuItem(new MenuItem(R.mipmap.pay,"付款"))
.setOnTopRightMenuItemClickListener(new OnTopRightMenuItemClickListener() {
@Override
public void onTopRightMenuItemClick(int position) {
Toast.makeText(MainActivity.this, " 点击位置 :" + position, Toast.LENGTH_SHORT).show();
}
});
mTopRightMenu.show(v,null,null);
}
});
}
private void initMenu() {
mItems = new ArrayList<>();
mItems.add(new MenuItem(R.mipmap.multichat, "发起多人聊天"));
mItems.add(new MenuItem(R.mipmap.addmember, "加好友"));
mItems.add(new MenuItem(R.mipmap.qr_scan, "扫一扫"));
}
}复制代码
其运行结果,如开头所示,这里主要是对上次 Path 的学习的巩固!下一次,我将继续站在大神肩膀上你们分享
附上本次 github 地址: github.com/Jooyer/Jooy…