package cn.mutils.app.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;
import cn.mutils.app.R;
import cn.mutils.app.ui.core.IDialog;
import cn.mutils.app.ui.core.IToastOwner;
import cn.mutils.app.ui.core.UICore;
import cn.mutils.app.util.AppUtil;
/**
* Dialog of framework
*/
@SuppressLint({"RtlHardcoded", "ShowToast", "InlinedApi"})
@SuppressWarnings({"deprecation", "unused"})
public class Dialoger extends Dialog implements IDialog {
protected InfoToast mInfoToast;
protected Toast mToast;
public Dialoger(Context context) {
super(context);
init(context);
}
public Dialoger(Context context, int theme) {
super(context, theme);
init(context);
}
public Dialoger(Context context, boolean cancelable, OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
init(context);
}
protected void init(Context context) {
this.setCancelable(true);
this.setCanceledOnTouchOutside(true);
Window w = getWindow();
w.requestFeature(Window.FEATURE_NO_TITLE);
w.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
w.setBackgroundDrawable(new ColorDrawable(0x00000000));
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
w.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
View decor = w.getDecorView();
decor.setPadding(decor.getPaddingLeft(), decor.getPaddingTop() + AppUtil.getStatusBarHeight(getContext()),
decor.getPaddingRight(), decor.getPaddingBottom());
}
UICore.injectContentView(this);
}
/**
* clear window animations
*/
public void clearAnimation() {
setWindowAnimations(R.style.DialogerNoAnim);
}
/**
* clear black blur background of Dialog
*/
public void clearBehind() {
getWindow()
.clearFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND | WindowManager.LayoutParams.FLAG_DIM_BEHIND);
}
/**
* fix bug of default Dialog width not full screen. please call before show
* and after setContentView if you want to make width MATCH_PARENT
*/
public void requestHFill() {
Window w = getWindow();
WindowManager.LayoutParams attrs = w.getAttributes();
w.setLayout(WindowManager.LayoutParams.MATCH_PARENT, attrs.height);
}
/**
* Make width and height to be MATCH_PARENT
*/
public void requestFill() {
getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
}
public Activity getActivity() {
return AppUtil.toActivity(getContext());
}
public Resources getResources() {
return getContext().getResources();
}
public void setWindowAnimations(int resId) {
Window w = getWindow();
w.setWindowAnimations(resId);
}
public <T extends View> T findViewById(int id, Class<T> viewClass) {
return UICore.findViewById(this, id, viewClass);
}
@Override
public void setContentView(int layoutResID) {
super.setContentView(layoutResID);
UICore.injectResources(this);
UICore.injectEvents(this);
}
@Override
public void setContentView(View view) {
super.setContentView(view);
UICore.injectResources(this);
UICore.injectEvents(this);
}
@Override
public void setContentView(View view, LayoutParams params) {
super.setContentView(view, params);
UICore.injectResources(this);
UICore.injectEvents(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
UICore.dispatchTouchEvent(ev, this);
return super.dispatchTouchEvent(ev);
}
public View getContentView() {
return UICore.getContentView(this);
}
@Override
public InfoToast getInfoToast() {
return mInfoToast;
}
@Override
public Toast getToast() {
Context context = this.getContext();
if (context instanceof IToastOwner) {
return ((IToastOwner) context).getToast();
}
if (mToast == null) {
mToast = Toast.makeText(context, "", Toast.LENGTH_SHORT);
}
return mToast;
}
@Override
public IToastOwner getToastOwner() {
return this;
}
@Override
public void toast(CharSequence s) {
UICore.toast(this, s);
}
@Override
public void toast(int resId, Object... args) {
UICore.toast(this, resId, args);
}
@Override
public void show() {
try {
super.show();
} catch (Exception e) {
// android.view.WindowManager.BadTokenException
}
}
@Override
public void dismiss() {
try {
super.dismiss();
} catch (Exception e) {
// java.lang.IllegalArgumentException
}
}
/**
* Simulate PopupWindow
*/
public void showAsDropDown(View anchor) {
clearBehind();
int[] location = new int[2];
anchor.getLocationOnScreen(location);
Rect dialogableRect = new Rect();
anchor.getWindowVisibleDisplayFrame(dialogableRect);
int screenHeight = anchor.getResources().getDisplayMetrics().heightPixels;
int maxStatusHeight = screenHeight / 10;// suppose max status bar height
boolean statusAtTop = dialogableRect.top > 1;
int statusHeight = statusAtTop ? dialogableRect.top : (screenHeight - dialogableRect.bottom);
statusHeight = statusHeight < maxStatusHeight ? statusHeight : 0;
// keyboard opening
if (statusHeight + dialogableRect.height() != screenHeight) {
dialogableRect.bottom = statusAtTop ? screenHeight : (screenHeight - statusHeight);
}
Window w = getWindow();
WindowManager.LayoutParams attrs = w.getAttributes();
attrs.y = location[1] + anchor.getHeight() - dialogableRect.top;
attrs.gravity = Gravity.LEFT | Gravity.TOP;
attrs.width = WindowManager.LayoutParams.MATCH_PARENT;
int maxHeight = dialogableRect.height() - attrs.y;
DropDownFrame frame = new DropDownFrame(getContext());
frame.setMaxHeight(maxHeight);
ViewGroup rootView = (ViewGroup) w.findViewById(android.R.id.content);
if (rootView.getChildCount() != 0) {
View v = rootView.getChildAt(0);
rootView.removeViewAt(0);
frame.addView(v);
}
frame.setLayoutParams(
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
w.setContentView(frame);
show();
}
/**
* Drop down frame for {@link Dialoger#showAsDropDown(View)} who has max
* height.
*/
protected static class DropDownFrame extends FrameLayout {
protected int mMaxHeight;
public DropDownFrame(Context context) {
super(context);
}
public DropDownFrame(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DropDownFrame(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setMaxHeight(int maxHeight) {
mMaxHeight = maxHeight;
this.requestLayout();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measuredHeight = this.getMeasuredHeight();
if (mMaxHeight > 0 && mMaxHeight < measuredHeight) {
// Notify sub views
super.onMeasure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mMaxHeight, MeasureSpec.EXACTLY));
this.setMeasuredDimension(getMeasuredWidth(), mMaxHeight);
}
}
}
}