package cn.mutils.app.ui;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.ScrollView;
import cn.mutils.app.ui.adapter.PopMenuAdapter;
import cn.mutils.app.ui.core.IStatusBarOwner;
import cn.mutils.app.util.AppUtil;
@SuppressWarnings({"deprecation", "unused"})
public class PopMenu<DATA_ITEM> {
protected View mAnchor;
protected PopupWindow mPopupWindow;
protected PopMenuAdapter<DATA_ITEM> mAdapter;
protected PopMenuListener mListener;
protected int mBackgroundRes;
protected int mPopupX;
protected int mPopupY;
public PopMenu(View anchor) {
Context context = anchor.getContext();
if (!(context instanceof Activity)) {
throw new IllegalArgumentException("Context is not Activity");
}
int[] anchorLocation = new int[2];
mAnchor = anchor;
mAnchor.getLocationOnScreen(anchorLocation);
mPopupX = anchorLocation[0];
mPopupY = anchorLocation[1];
}
public void setAdapter(PopMenuAdapter<DATA_ITEM> adapter) {
if (mPopupWindow != null) {
return;
}
if (adapter.getContainer() != null) {
throw new IllegalArgumentException("I will set container by myslef");
}
mAdapter = adapter;
mAdapter.setPopMenu(this);
}
public void setListener(PopMenuListener listener) {
mListener = listener;
}
public void dismiss() {
if (mPopupWindow != null) {
mPopupWindow.dismiss();
}
}
public void setBackgroundRes(int backgroundRes) {
if (mPopupWindow != null) {
return;
}
mBackgroundRes = backgroundRes;
}
public void show() {
if (mPopupWindow != null) {
return;
}
Context context = mAnchor.getContext();
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
int screenHeight = metrics.heightPixels;
int padding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, metrics);
Rect popupArea = new Rect();
((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(popupArea);
boolean statusBarAtTop = popupArea.top > 1;
boolean statusBarTranslucent = (context instanceof IStatusBarOwner)
&& ((IStatusBarOwner) context).isStatusBarTranslucent();
if (statusBarTranslucent) {
statusBarAtTop = true;// Do not know how to do with this case.
}
int popupAreaHeight = popupArea.height();
int statusBarHeight = screenHeight - popupAreaHeight;
if (statusBarTranslucent) {
statusBarHeight = AppUtil.getStatusBarHeight(context);
}
int anchorHeight = mAnchor.getHeight();
int halfPopupAreaHeight = popupAreaHeight >> 1;
boolean underAnchor = (mPopupY - popupArea.top + (anchorHeight >> 1)) < halfPopupAreaHeight;
mPopupY = underAnchor ? (mPopupY + anchorHeight + padding) : (mPopupY - padding);
int contentMaxHeight = underAnchor ? (screenHeight - mPopupY - padding - (statusBarAtTop ? 0 : statusBarHeight))
: (mPopupY - padding - (statusBarAtTop ? statusBarHeight : 0));
FrameLayout realContentView = new FrameLayout(context);
realContentView.setPadding(padding, 0, padding, 0);
OPopupMenuScroller scroller = new OPopupMenuScroller(context);
scroller.setVerticalScrollBarEnabled(false);
if (mBackgroundRes != 0) {
scroller.setBackgroundResource(mBackgroundRes);
} else {
GradientDrawable scrollerDrawable = new GradientDrawable();
scrollerDrawable.setColor(0xFFF5F5F5);
scrollerDrawable.setStroke(1, 0xD9D9D9D9);
scroller.setBackgroundDrawable(scrollerDrawable);
}
scroller.setMaxHeight(contentMaxHeight);
if (!underAnchor) {
scroller.setOnMeasuredListener(new OnMeasuredListener() {
@Override
public void onMeasured(View v, int width, int height) {
((OPopupMenuScroller) v).setOnMeasuredListener(null);
mPopupY = mPopupY - height;
mPopupWindow.update(mPopupX, mPopupY, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);
}
});
}
LinearLayout scrollContent = new LinearLayout(context);
scrollContent.setOrientation(LinearLayout.VERTICAL);
if (mAdapter != null) {
mAdapter.setContainer(scrollContent);
}
scroller.addView(scrollContent, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
realContentView.addView(scroller, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
mPopupWindow = new PopupWindow(realContentView, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT);
mPopupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setFocusable(true);
mPopupWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, mPopupX, mPopupY);
mPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
if (mListener != null) {
mListener.onDismiss();
}
mPopupWindow = null;
}
});
}
public static interface PopMenuListener {
public void onDismiss();
}
protected static interface OnMeasuredListener {
public void onMeasured(View v, int width, int height);
}
protected static class OPopupMenuScroller extends ScrollView {
protected int mMaxHeight;
protected int mMaxWidth;
protected OnMeasuredListener mOnMeasuredListener;
public OPopupMenuScroller(Context context) {
super(context);
}
public OPopupMenuScroller(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OPopupMenuScroller(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredWidth = this.getMeasuredWidth();
int measuredHeight = this.getMeasuredHeight();
boolean measuredChanged = false;
if (mMaxWidth > 0 && measuredWidth > mMaxWidth) {
measuredWidth = mMaxWidth;
measuredChanged = true;
}
if (mMaxHeight > 0 && measuredHeight > mMaxHeight) {
measuredHeight = mMaxHeight;
measuredChanged = true;
}
if (measuredChanged) {
this.setMeasuredDimension(measuredWidth, measuredHeight);
}
if (mOnMeasuredListener != null) {
mOnMeasuredListener.onMeasured(this, measuredWidth, measuredHeight);
}
}
public int getMaxHeight() {
return mMaxHeight;
}
public void setMaxHeight(int maxHeight) {
this.mMaxHeight = maxHeight;
}
public int getMaxWidth() {
return mMaxWidth;
}
public void setMaxWidth(int maxWidth) {
this.mMaxWidth = maxWidth;
}
public void setOnMeasuredListener(OnMeasuredListener listener) {
mOnMeasuredListener = listener;
}
}
}