Created
November 17, 2015 18:33
-
-
Save slightfoot/2a57cd2f400be38f8f5c to your computer and use it in GitHub Desktop.
Action Panel Helper - For those popup panels from Action Buttons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.PixelFormat; | |
import android.os.Build; | |
import android.support.annotation.LayoutRes; | |
import android.util.AttributeSet; | |
import android.view.Gravity; | |
import android.view.KeyEvent; | |
import android.view.LayoutInflater; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.WindowManager; | |
import android.widget.FrameLayout; | |
/** | |
* Action Panel Helper | |
* <p> | |
* Created by Simon Lightfoot on 15/11/2015. | |
*/ | |
public class ActionPanelHelper | |
{ | |
private final Context mContext; | |
private final WindowManager mWindowManager; | |
private WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(); | |
private boolean mShowing = false; | |
private PopupFrame mPopupFrame; | |
private View mContentView; | |
private int mAnimationStyle = -1; | |
private int mSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED; | |
private boolean mFocusable = true; | |
private OnDismissListener mOnDismissListener; | |
public ActionPanelHelper(Context context) | |
{ | |
mContext = context; | |
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); | |
} | |
public View setContentView(View view) | |
{ | |
mContentView = view; | |
if(mPopupFrame == null){ | |
mPopupFrame = new PopupFrame(mContext, null); | |
} | |
mPopupFrame.removeAllViews(); | |
mPopupFrame.addView(mContentView); | |
return mContentView; | |
} | |
public View setContentView(@LayoutRes int layoutResId) | |
{ | |
setContentView(LayoutInflater.from(mContext).inflate(layoutResId, null)); | |
return mContentView; | |
} | |
public View getContentView() | |
{ | |
return mContentView; | |
} | |
public void setSoftInputMode(int softInputMode) | |
{ | |
mSoftInputMode = softInputMode; | |
} | |
public void setFocusable(boolean focusable) | |
{ | |
mFocusable = focusable; | |
} | |
public void setOnDismissListener(OnDismissListener onDismissListener) | |
{ | |
mOnDismissListener = onDismissListener; | |
} | |
public void show(View anchor, int horizontalMargin, int verticalMargin) | |
{ | |
if(!mShowing){ | |
int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); | |
mPopupFrame.measure(measureSpec, measureSpec); | |
int[] location = new int[2]; | |
anchor.getLocationInWindow(location); | |
mLayoutParams.x = (location[0] + anchor.getWidth()) - (mPopupFrame.getMeasuredWidth() - horizontalMargin); | |
mLayoutParams.y = location[1] + verticalMargin; | |
mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; | |
mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; | |
mLayoutParams.gravity = Gravity.START | Gravity.TOP; | |
mLayoutParams.flags = | |
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | | |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | | |
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; | |
if(!mFocusable){ | |
mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; | |
if(mSoftInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED){ | |
mLayoutParams.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; | |
} | |
} | |
mLayoutParams.softInputMode = mSoftInputMode; | |
mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION; | |
mLayoutParams.format = PixelFormat.TRANSLUCENT; | |
mLayoutParams.windowAnimations = mAnimationStyle; | |
mWindowManager.addView(mPopupFrame, mLayoutParams); | |
mShowing = true; | |
} | |
} | |
public boolean isShowing() | |
{ | |
return mShowing; | |
} | |
public void dismiss() | |
{ | |
if(mShowing){ | |
mWindowManager.removeView(mPopupFrame); | |
mShowing = false; | |
if(mOnDismissListener != null){ | |
mOnDismissListener.onDismiss(); | |
} | |
} | |
} | |
private class PopupFrame extends FrameLayout | |
{ | |
@SuppressWarnings("deprecation") | |
public PopupFrame(Context context, AttributeSet attrs) | |
{ | |
super(context, attrs); | |
int[] ATTRS = { | |
android.R.attr.popupBackground, | |
android.R.attr.popupAnimationStyle, | |
}; | |
TypedArray a = context.obtainStyledAttributes(attrs, ATTRS, | |
R.attr.listPopupWindowStyle, 0); | |
if(a.hasValue(0)){ | |
setBackgroundDrawable(a.getDrawable(0)); | |
} | |
if(a.hasValue(1)){ | |
mAnimationStyle = a.getResourceId(1, 0); | |
} | |
a.recycle(); | |
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ | |
int[] ATTRS_L = { android.R.attr.popupElevation }; | |
a = context.obtainStyledAttributes(attrs, ATTRS_L, | |
R.attr.listPopupWindowStyle, 0); | |
if(a.hasValue(0)){ | |
setElevation(a.getDimension(0, 0)); | |
} | |
a.recycle(); | |
} | |
} | |
@Override | |
public boolean onTouchEvent(MotionEvent event) | |
{ | |
final int x = (int) event.getX(); | |
final int y = (int) event.getY(); | |
if((event.getAction() == MotionEvent.ACTION_DOWN) && | |
((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) | |
{ | |
dismiss(); | |
return true; | |
} | |
else if(event.getAction() == MotionEvent.ACTION_OUTSIDE){ | |
dismiss(); | |
return true; | |
} | |
else{ | |
return super.onTouchEvent(event); | |
} | |
} | |
@Override | |
public boolean dispatchKeyEvent(KeyEvent event) | |
{ | |
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK){ | |
final KeyEvent.DispatcherState state = getKeyDispatcherState(); | |
if(state == null){ | |
return super.dispatchKeyEvent(event); | |
} | |
if(event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0){ | |
state.startTracking(event, this); | |
return true; | |
} | |
else if(event.getAction() == KeyEvent.ACTION_UP){ | |
if(state.isTracking(event) && !event.isCanceled()){ | |
dismiss(); | |
return true; | |
} | |
} | |
return super.dispatchKeyEvent(event); | |
} | |
else{ | |
return super.dispatchKeyEvent(event); | |
} | |
} | |
} | |
public interface OnDismissListener { | |
void onDismiss(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example of its use.