当前位置:网站首页>Popupwindow utility class

Popupwindow utility class

2022-06-26 03:37:00 kingsley1212

PopupWindow Tool class , Quick realization of spring frame function

The following code is Java Version of
public PopwindowJavaUtil(Context context) {
    this.mContext = context;
}

/**
 *  Position relative to a control   With offset 
 *
 * @param anchor  Specify the relative position of which control it is located 
 * @param x
 * @param y
 * @return
 */
public PopwindowJavaUtil showAsDropDown(View anchor, int x, int y) {
    mPopupWindow.showAsDropDown(anchor, x, y);
    return this;
}

public PopwindowJavaUtil showAsDropDown(View anchor) {
    mPopupWindow.showAsDropDown(anchor);
    return this;
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public PopwindowJavaUtil showAsDropDown(View anchor, int xOff, int yOff, int gravity) {
    mPopupWindow.showAsDropDown(anchor, xOff, yOff, gravity);
    return this;
}

/**
 *  Position relative to parent control 
 *
 * @param parent
 * @param gravity
 * @param x
 * @param y
 * @return
 */
public PopwindowJavaUtil showAtLocation(View parent, int x, int y, int gravity) {
    mPopupWindow.showAtLocation(parent, x, y, gravity);
    return this;
}

/**
 *  Set a shaded background 
 */
public PopwindowJavaUtil showAtLocation(View parent, int x, int y, int gravity, final float bgAlpha) {
    backgroundAlpha(bgAlpha, true);
    mPopupWindow.showAtLocation(parent, gravity, x, y);
    mPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
        @Override
        public void onDismiss() {
            backgroundAlpha(bgAlpha, false);
        }
    });
    return this;
}

public PopwindowJavaUtil showAtLocation(View root) {
    int[] windowPos = calculatePopWindowPos(root, mContentView);
    int xOff = 10;// You can adjust the offset by yourself 
    windowPos[0] -= xOff;
    mPopupWindow.showAtLocation(root, Gravity.TOP | Gravity.START,
            windowPos[0], windowPos[1]);
    return this;
}

/**
 *  Add attribute 
 *
 * @param popupWindow
 */
private void apply(PopupWindow popupWindow) {
    popupWindow.setClippingEnabled(mClippEnable);
    if (mIgnoreCheekPress) {
        popupWindow.setIgnoreCheekPress();
    }
    if (mInputMode != -1) {
        popupWindow.setInputMethodMode(mInputMode);
    }
    if (mSoftInputMode != -1) {
        popupWindow.setSoftInputMode(mSoftInputMode);
    }
    if (mOnDismissListener != null) {
        popupWindow.setOnDismissListener(mOnDismissListener);
    }
    if (mOnTouchListener != null) {
        popupWindow.setTouchInterceptor(mOnTouchListener);
    }
    popupWindow.setTouchable(mTouchable);

}

private PopupWindow build() {
    if (mContentView == null) {
        mContentView = LayoutInflater.from(mContext).inflate(mResLayoutId, null);
    }
    if (mWidth != 0f && mHeight != 0f) {
        mPopupWindow = new PopupWindow(mContentView, (int) mWidth, (int) mHeight);
    } else {
        mPopupWindow = new PopupWindow(mContentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    }
    if (mAninationStyle != -1) {
        mPopupWindow.setAnimationStyle(mAninationStyle);
    }
    if (mElevation != 0f) {
        mPopupWindow.setElevation(mElevation);
    }
    apply(mPopupWindow);// Set some properties 
    mPopupWindow.setFocusable(mIsFocusable);
    if (null != mBackgroundDrawable) {
        mPopupWindow.setBackgroundDrawable(mBackgroundDrawable);
    }
    mPopupWindow.setOutsideTouchable(mIsOutside);
    if (mWidth == 0f || mHeight == 0f) {
        mPopupWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        mWidth = mPopupWindow.getContentView().getMeasuredWidth();
        mHeight = mPopupWindow.getContentView().getMinimumHeight();
    }
    mPopupWindow.update();
    return mPopupWindow;
}

public View getView(int resId) {
    View view = sparseArray.get(resId);
    if (mContentView == null) {
        Log.i("PopwindowJavaUtil", "mContentView is null!");
        return null;
    }
    if (view == null) {
        view = mContentView.findViewById(resId);
        sparseArray.put(resId, view);
    }
    return view;
}

public void setText(int resId, String text) {
    TextView textView = (TextView) getView(resId);
    textView.setText(text);
}

public void dissmiss() {
    if (mPopupWindow != null) {
        mPopupWindow.dismiss();
    }
}

public static class PopupWindowBuilder {
    private PopwindowJavaUtil mCustomPopWindow;

    public PopupWindowBuilder(Context context) {
        mCustomPopWindow = new PopwindowJavaUtil(context);
    }

    public PopupWindowBuilder size(float width, float height) {
        mCustomPopWindow.mWidth = width;
        mCustomPopWindow.mHeight = height;
        return this;
    }

    public PopupWindowBuilder setFocusable(boolean focusable) {
        mCustomPopWindow.mIsFocusable = focusable;
        return this;
    }

    public PopupWindowBuilder setView(int resLayoutId) {
        mCustomPopWindow.mResLayoutId = resLayoutId;
        mCustomPopWindow.mContentView = null;
        return this;
    }

    public PopupWindowBuilder setView(View view) {
        mCustomPopWindow.mContentView = view;
        mCustomPopWindow.mResLayoutId = -1;
        return this;
    }

    public PopupWindowBuilder setElevation(Float elevation) {
        mCustomPopWindow.mElevation = elevation;
        return this;
    }

    public PopupWindowBuilder setOutsideTouchable(Boolean outsideTouchable) {
        mCustomPopWindow.mIsOutside = outsideTouchable;
        return this;
    }

    /**
     *  Set pop-up animation 
     *
     * @param animationStyle
     * @return
     */
    public PopupWindowBuilder setAnimationStyle(int animationStyle) {
        mCustomPopWindow.mAninationStyle = animationStyle;
        return this;
    }

    public PopupWindowBuilder setClippingEnable(Boolean enable) {
        mCustomPopWindow.mClippEnable = enable;
        return this;
    }

    public PopupWindowBuilder setIgnoreCheekPress(Boolean ignoreCheekPress) {
        mCustomPopWindow.mIgnoreCheekPress = ignoreCheekPress;
        return this;
    }

    public PopupWindowBuilder setInputMethodMode(int mode) {
        mCustomPopWindow.mInputMode = mode;
        return this;
    }

    public PopupWindowBuilder setOnDissmissListener(PopupWindow.OnDismissListener onDissmissListener) {
        mCustomPopWindow.mOnDismissListener = onDissmissListener;
        return this;
    }

    public PopupWindowBuilder setSoftInputMode(int softInputMode) {
        mCustomPopWindow.mSoftInputMode = softInputMode;
        return this;
    }

    public PopupWindowBuilder setTouchable(Boolean touchable) {
        mCustomPopWindow.mTouchable = touchable;
        return this;
    }

    public PopupWindowBuilder setTouchIntercepter(View.OnTouchListener touchIntercepter) {
        mCustomPopWindow.mOnTouchListener = touchIntercepter;
        return this;
    }

    public PopupWindowBuilder setBackgroundDrawable(Drawable drawable) {
        mCustomPopWindow.mBackgroundDrawable = drawable;
        return this;
    }

    public PopwindowJavaUtil create() {
        mCustomPopWindow.build();
        return mCustomPopWindow;
    }
}

private int[] calculatePopWindowPos(View anchorView, View contentView) {
    int[] windowPos = new int[2];
    int[] anchorLoc = new int[2];
    //  Get anchors View Coordinate position in the upper left corner of the screen 
    anchorView.getLocationOnScreen(anchorLoc);
    int anchorHeight = anchorView.getHeight();
    //  Get the height and width of the screen 
    int screenHeight = getScreenHeight(anchorView.getContext());
    int screenWidth = getScreenWidth(anchorView.getContext());
    contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
    //  Calculation contentView Height and width of 
    int windowHeight = contentView.getMeasuredHeight();
    int windowWidth = contentView.getMeasuredWidth();
    //  Determine whether you need to pop up or pop down 
    boolean isNeedShowUp = screenHeight - anchorLoc[1] - anchorHeight < windowHeight;
    if (isNeedShowUp) {
        windowPos[0] = screenWidth - windowWidth;
        windowPos[1] = anchorLoc[1] - windowHeight;
    } else {
        windowPos[0] = screenWidth - windowWidth;
        windowPos[1] = anchorLoc[1] + anchorHeight;
    }
    return windowPos;
}

private int getScreenWidth(Context context) {
    return context.getResources().getDisplayMetrics().heightPixels;
}

private int getScreenHeight(Context context) {
    return context.getResources().getDisplayMetrics().widthPixels;
}

private boolean isStarted = false;
float mCurrentAlpha;
ValueAnimator animation;

private void backgroundAlpha(float bgAlpha, boolean show) {
    if (isStarted) {
        return;
    }
    isStarted = true;
    ValueAnimator animator = null;
    if (show) {
        animator = ValueAnimator.ofFloat(1f, bgAlpha).setDuration(500);
    } else {
        animator = ValueAnimator.ofFloat(bgAlpha, 1f).setDuration(500);
    }

    ValueAnimator.AnimatorUpdateListener updateListener = new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation1) {
            mCurrentAlpha = (float) animation1.getAnimatedValue();
            animation = animation1;
            WindowManager.LayoutParams lp = ((Activity) mContext).getWindow().getAttributes();
            lp.alpha = mCurrentAlpha;
            ((Activity) mContext).getWindow().setAttributes(lp);
        }
    };
    Animator.AnimatorListener animatorListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            // The animation is over 
            isStarted = false;
        }
    };

    animator.addUpdateListener(updateListener);
    animator.addListener(animatorListener);
    animator.start();
	 }
}

kotlin Version as follows

class PopwindowUtil private constructor(private val mContext: Context) {
	var mWidth = 0f
	var mHeight = 0f
 	private var mIsFocusable = true
 	private var mIsOutside = true
 	private var mResLayoutId = -1
  	var mContentView: View? = null
	private var mPopupWindow: PopupWindow? = null
	private var mAnimationStyle = -1
	private var mElevation :Float = 0f
	private var mClippEnable = true//default is true
	private var mIgnoreCheekPress = false
	private var mInputMode = -1
	private var mOnDismissListener: PopupWindow.OnDismissListener? = null
	private var mSoftInputMode = -1
	private var mTouchable = true//default is ture
	private var mOnTouchListener: View.OnTouchListener? = null
	private var mBackgroundDrawable: Drawable? = null

private val sparseArray = SparseArray<View>()

/**
 *  Position relative to a control   With offset 
 * @param anchor  Specify the relative position of which control it is located 
 * @param x
 * @param y
 * @return
 */
fun showAsDropDown(anchor: View, x: Int, y: Int): PopwindowUtil {
    mPopupWindow?.showAsDropDown(anchor, x, y)
    return this
}

fun showAsDropDown(anchor: View): PopwindowUtil {
    mPopupWindow?.showAsDropDown(anchor)
    return this
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
fun showAsDropDown(anchor: View, xOff: Int, yOff: Int, gravity: Int): PopwindowUtil {
    mPopupWindow?.showAsDropDown(anchor, xOff, yOff, gravity)
    return this
}

/**
 *  Position relative to parent control 
 * @param parent
 * @param gravity
 * @param x
 * @param y
 * @return
 */
fun showAtLocation(parent: View, x: Int, y: Int ,gravity: Int): PopwindowUtil {
    mPopupWindow?.showAtLocation(parent, gravity, x, y)
    return this
}

/**
 *  Set a shaded background 
 */
fun showAtLocation(parent: View, x: Int, y: Int ,gravity: Int,bgAlpha: Float): PopwindowUtil {
    backgroundAlpha(bgAlpha,true)
    mPopupWindow?.let {
        it.showAtLocation(parent, gravity, x, y)
        it.setOnDismissListener {
            backgroundAlpha(bgAlpha,false)
        }
    }
    return this
}

fun showAtLocation(root: View): PopwindowUtil {
    val windowPos = calculatePopWindowPos(root, mContentView!!)
    val xOff = 10//  You can adjust the offset by yourself 
    windowPos[0] -= xOff
    mPopupWindow?.showAtLocation(
        root, Gravity.TOP or Gravity.START,
        windowPos[0], windowPos[1]
    )
    return this
}

/**
 *  Add attribute 
 * @param popupWindow
 */
private fun apply(popupWindow: PopupWindow) {
    popupWindow.isClippingEnabled = mClippEnable
    if (mIgnoreCheekPress) {
        popupWindow.setIgnoreCheekPress()
    }
    if (mInputMode != -1) {
        popupWindow.inputMethodMode = mInputMode
    }
    if (mSoftInputMode != -1) {
        popupWindow.softInputMode = mSoftInputMode
    }
    if (mOnDismissListener != null) {
        popupWindow.setOnDismissListener(mOnDismissListener)
    }
    if (mOnTouchListener != null) {
        popupWindow.setTouchInterceptor(mOnTouchListener)
    }
    popupWindow.isTouchable = mTouchable
}

private fun build(): PopupWindow {

    if (mContentView == null) {
        mContentView = LayoutInflater.from(mContext).inflate(mResLayoutId, null)
    }

    if (mWidth != 0f && mHeight != 0f) {
        mPopupWindow = PopupWindow(mContentView, mWidth.toInt(), mHeight.toInt())
    } else {
        mPopupWindow =
            PopupWindow(mContentView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
    }
    if (mAnimationStyle != -1) {
        mPopupWindow!!.animationStyle = mAnimationStyle
    }
    if (mElevation != 0f){
        mPopupWindow!!.elevation = mElevation;
    }

    apply(mPopupWindow!!)// Set some properties 

    mPopupWindow!!.isFocusable = mIsFocusable
    if (null != mBackgroundDrawable) {
        mPopupWindow!!.setBackgroundDrawable(mBackgroundDrawable)
    }
    mPopupWindow!!.isOutsideTouchable = mIsOutside

    if (mWidth == 0f || mHeight == 0f) {
        mPopupWindow!!.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
        // If no width or height is set outside , Calculate the width and height and assign values 
        mWidth = mPopupWindow!!.contentView.measuredWidth.toFloat()
        mHeight = mPopupWindow!!.contentView.measuredHeight.toFloat()
    }

    mPopupWindow!!.update()

    return mPopupWindow!!
}

fun <T : View> getView(resId: Int): T? {
    var view: View? = sparseArray.get(resId)
    if (mContentView == null) {
        Log.i("PopwindowUtil", "mContentView is null!")
        return null
    }
    if (view == null) {
        view = mContentView!!.findViewById(resId)
        sparseArray.put(resId, view)
    }
    return view as T?
}

fun setText(resId: Int, text: String) {
    val textView = getView<TextView>(resId)
    textView!!.text = text
}

fun dissmiss() {
    if (mPopupWindow != null) {
        mPopupWindow!!.dismiss()
    }
}

class PopupWindowBuilder(context: Context) {
    private val mCustomPopWindow: PopwindowUtil

    init {
        mCustomPopWindow = PopwindowUtil(context)
    }

    fun size(width: Float, height: Float): PopupWindowBuilder {
        mCustomPopWindow.mWidth = width
        mCustomPopWindow.mHeight = height
        return this
    }


    fun setFocusable(focusable: Boolean): PopupWindowBuilder {
        mCustomPopWindow.mIsFocusable = focusable
        return this
    }


    fun setView(resLayoutId: Int): PopupWindowBuilder {
        mCustomPopWindow.mResLayoutId = resLayoutId
        mCustomPopWindow.mContentView = null
        return this
    }

    fun setView(view: View): PopupWindowBuilder {
        mCustomPopWindow.mContentView = view
        mCustomPopWindow.mResLayoutId = -1
        return this
    }

    fun setElevation(elevation :Float): PopupWindowBuilder {
        mCustomPopWindow.mElevation = elevation
        return this
    }

    fun setOutsideTouchable(outsideTouchable: Boolean): PopupWindowBuilder {
        mCustomPopWindow.mIsOutside = outsideTouchable
        return this
    }

    /**
     *  Set pop-up animation 
     * @param animationStyle
     * @return
     */
    fun setAnimationStyle(animationStyle: Int): PopupWindowBuilder {
        mCustomPopWindow.mAnimationStyle = animationStyle
        return this
    }


    fun setClippingEnable(enable: Boolean): PopupWindowBuilder {
        mCustomPopWindow.mClippEnable = enable
        return this
    }


    fun setIgnoreCheekPress(ignoreCheekPress: Boolean): PopupWindowBuilder {
        mCustomPopWindow.mIgnoreCheekPress = ignoreCheekPress
        return this
    }

    fun setInputMethodMode(mode: Int): PopupWindowBuilder {
        mCustomPopWindow.mInputMode = mode
        return this
    }

    fun setOnDissmissListener(onDissmissListener: PopupWindow.OnDismissListener): PopupWindowBuilder {
        mCustomPopWindow.mOnDismissListener = onDissmissListener
        return this
    }


    fun setSoftInputMode(softInputMode: Int): PopupWindowBuilder {
        mCustomPopWindow.mSoftInputMode = softInputMode
        return this
    }


    fun setTouchable(touchable: Boolean): PopupWindowBuilder {
        mCustomPopWindow.mTouchable = touchable
        return this
    }

    fun setTouchIntercepter(touchIntercepter: View.OnTouchListener): PopupWindowBuilder {
        mCustomPopWindow.mOnTouchListener = touchIntercepter
        return this
    }

    fun setBackgroundDrawable(drawable: Drawable): PopupWindowBuilder {
        mCustomPopWindow.mBackgroundDrawable = drawable
        return this
    }

    fun create(): PopwindowUtil {
        // structure PopWindow
        mCustomPopWindow.build()
        return mCustomPopWindow
    }

}

companion object {


    /**
     *  Calculated position ,y The direction is anchorView Align the top and bottom of the display ,x The direction is aligned with the right side of the screen 
     *  If anchorView The position of the has changed , You can properly add an additional offset to correct 
     * @param anchorView   Exhale window Of view
     * @param contentView   window The content layout of 
     * @return window In the upper left corner of the display xOff,yOff coordinate 
     */
    private fun calculatePopWindowPos(anchorView: View, contentView: View): IntArray {
        val windowPos = IntArray(2)
        val anchorLoc = IntArray(2)
        //  Get anchors View Coordinate position in the upper left corner of the screen 
        anchorView.getLocationOnScreen(anchorLoc)
        val anchorHeight = anchorView.height
        //  Get the height and width of the screen 
        val screenHeight = getScreenHeight(anchorView.context)
        val screenWidth = getScreenWidth(anchorView.context)
        contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED)
        //  Calculation contentView Height and width of 
        val windowHeight = contentView.measuredHeight
        val windowWidth = contentView.measuredWidth
        //  Determine whether you need to pop up or pop down 
        val isNeedShowUp = screenHeight - anchorLoc[1] - anchorHeight < windowHeight
        if (isNeedShowUp) {
            windowPos[0] = screenWidth - windowWidth
            windowPos[1] = anchorLoc[1] - windowHeight
        } else {
            windowPos[0] = screenWidth - windowWidth
            windowPos[1] = anchorLoc[1] + anchorHeight
        }
        return windowPos
    }

    /**
     *  Get screen height (px)
     */
    fun getScreenHeight(context: Context): Int {
        return context.resources.displayMetrics.heightPixels
    }

    /**
     *  Get screen width (px)
     */
    fun getScreenWidth(context: Context): Int {
        return context.resources.displayMetrics.widthPixels
    }
}

var isStarted = false
fun backgroundAlpha(bgAlpha:Float,show:Boolean) {
    if (isStarted){
        return
    }
    isStarted = true
    var animator:ValueAnimator
    if (show)
        animator = ValueAnimator.ofFloat(1f, bgAlpha).setDuration(500)
    else
        animator = ValueAnimator.ofFloat(bgAlpha, 1f).setDuration(500)
    getActivityFromContext(mContext)?.let {
        var updateListener = ValueAnimator.AnimatorUpdateListener { animation ->
            var mCurrentAlpha = (animation.animatedValue as Float)
            val lp = it.getWindow().getAttributes()
            lp.alpha = mCurrentAlpha
            it.getWindow().setAttributes(lp)
        }
        var animatorListener = object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                super.onAnimationEnd(animation)
                // The animation is over 
                isStarted = false
            }
        }
        animator.addUpdateListener(updateListener)
        animator.addListener(animatorListener)
        animator.start()
    }
}

/**
 *  Judge context 
 */
private fun getActivityFromContext(context: Context?): Activity? {
    var context = context
    if (null != context) {
        while (context is ContextWrapper) {
            if (context is Activity) {
                return context
            }else if (context is Fragment){
                return context.activity
            }
            context = context.baseContext
        }
    }
    return null
}
}

Usage method , Call the following methods when necessary

   val popwindowUtil = PopwindowJavaUtil.PopupWindowBuilder(activity!!)
                    .setView(R.layout.pop_detail_menu)// This is what you need to pop up view
                    .size(LinearLayout.LayoutParams.MATCH_PARENT.toFloat(), LinearLayout.LayoutParams.WRAP_CONTENT.toFloat())
                    .setAnimationStyle(R.style.contextMenuAnim)
                    .setFocusable(true)
                    .setTouchable(true)
                    .setOutsideTouchable(true)
                    .create()
            val rootview = LayoutInflater.from(activity)
                    .inflate(R.layout.frag_home, null)// This is your current page view
            popwindowUtil.showAtLocation(rootview,0,0, Gravity.BOTTOM,0.6f)

Pop up pop up animation

 <style name="contextMenuAnim" parent="@android:style/Animation.Activity">
        <item name="android:windowEnterAnimation">@anim/pop_show</item>
        <item name="android:windowExitAnimation">@anim/pop_hide</item>
    </style>

pop_show.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="@android:integer/config_mediumAnimTime"
     android:shareInterpolator="true"
>
    <translate
            android:fromXDelta="0"
            android:fromYDelta="100%p"
            android:interpolator="@android:anim/accelerate_decelerate_interpolator"
            android:toXDelta="0"
            android:toYDelta="0"/>
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
    />
</set>

pop_hide.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="@android:integer/config_mediumAnimTime"
     android:shareInterpolator="true"
>
    <translate
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:interpolator="@android:anim/linear_interpolator"
            android:toXDelta="0"
            android:toYDelta="100%p" />
    <alpha
            android:fromAlpha="1"
            android:toAlpha="0"
    />

</set>
原网站

版权声明
本文为[kingsley1212]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202180547452537.html