当前位置: 代码迷 >> Android >> 47.Android 自定义PopupWindow技能
  详细解决方案

47.Android 自定义PopupWindow技能

热度:297   发布时间:2016-04-24 12:01:08.0
47.Android 自定义PopupWindow技巧

47.Android 自定义PopupWindow技巧

  • Android 自定义PopupWindow技巧
    • 前言
    • PopupWindow的宽高
    • PopupWindow定位在下左位置
    • PopupWindow定位在下中位置
    • PopupWindow定位在下右位置
    • PopupWindow动画
    • 自定义PopupWindow
    • 效果图


前言

其实PopupWindow自定义过程是很简单的,唯一头疼的是:PopupWindow显示的定位问题。

定位问题尤为恶心一点:有时候要涉及到PopupWindow的宽高问题。我们都知道,在没show之前是拿不到宽高的,show的时候定位需要宽高,如此矛盾。以下,都给予回答

其次的问题也有:PopupWindow的显示、消失动画设计问题。

以下也在我自定义的PopupWindow中提供了三个简单的定位方法:

  • 显示在控件的下左位置

  • 显示在控件的下中位置

  • 显示在控件的下右位置


PopupWindow的宽高

我们可以在PopupWindow初始化的时候,强制绘制Layout,而拿到PopupWindow的宽高。

// 用于保存PopupWindow的宽度private int width;// 用于保存PopupWindow的高度private int height;public CustomPopupWindow(Activity activity) {    super(activity);    this.activity = activity;    this.initPopupWindow();}private void initPopupWindow() {    LayoutInflater inflater = (LayoutInflater) activity            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);    this.contentView = inflater.inflate(R.layout.popupwindow_custom, null);    this.setContentView(contentView);    // 设置弹出窗体的宽    this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);    // 设置弹出窗体的高    this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);    // 设置弹出窗体可点击    this.setTouchable(true);    this.setFocusable(true);    // 设置点击是否消失    this.setOutsideTouchable(true);    //设置弹出窗体动画效果    this.setAnimationStyle(R.style.PopupAnimation);    //实例化一个ColorDrawable颜色为半透明    ColorDrawable background = new ColorDrawable(0x4f000000);    //设置弹出窗体的背景    this.setBackgroundDrawable(background);    // 绘制    this.mandatoryDraw();}/** * 强制绘制popupWindowView,并且初始化popupWindowView的尺寸 */private void mandatoryDraw() {    this.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);    /**     * 强制刷新后拿到PopupWindow的宽高     */    this.width = this.contentView.getMeasuredWidth();    this.height = this.contentView.getMeasuredHeight();}

PopupWindow定位在下左位置

/** * 显示在控件的下左方 * * @param parent parent */public void showAtDropDownLeft(View parent) {    if (parent.getVisibility() == View.GONE) {        this.showAtLocation(parent, 0, 0, 0);    } else {        // x y        int[] location = new int[2];        //获取在整个屏幕内的绝对坐标        parent.getLocationOnScreen(location);        this.showAtLocation(parent, 0, location[0], location[1] + parent.getHeight());    }}

PopupWindow定位在下中位置

/** * 显示在控件的下中方 * * @param parent parent */public void showAtDropDownCenter(View parent) {    if (parent.getVisibility() == View.GONE) {        this.showAtLocation(parent, 0, 0, 0);    } else {        // x y        int[] location = new int[2];        //获取在整个屏幕内的绝对坐标        parent.getLocationOnScreen(location);        this.showAtLocation(parent, 0, location[0] / 2 + parent.getWidth() / 2 - this.width / 6, location[1] + parent.getHeight());    }}

PopupWindow定位在下右位置

/** * 显示在控件的下右方 * * @param parent parent */public void showAtDropDownRight(View parent) {    if (parent.getVisibility() == View.GONE) {        this.showAtLocation(parent, 0, 0, 0);    } else {        // x y        int[] location = new int[2];        //获取在整个屏幕内的绝对坐标        parent.getLocationOnScreen(location);        this.showAtLocation(parent, 0, location[0] + parent.getWidth() - this.width, location[1] + parent.getHeight());    }}

PopupWindow动画

设计一个从PopWindow开始的时候右上角逐步展示,然后结束的时候往右上角逐步收起的动画:

styles.xml

<style name="PopupAnimation" parent="android:Animation" mce_bogus="1">    <item name="android:windowEnterAnimation">@anim/popwindow_in</item>    <item name="android:windowExitAnimation">@anim/popwindow_out</item></style>

popwindow_in.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/decelerate_interpolator">    <!--        时间 0.2秒        开始的时候 x y 全是0 没有大小        结束的时候 x y 全是1 实际大小        pivotX 100% 表示最右边        pivotY 0% 表示最顶边        以上定位右上角 缩放时不变位置    -->    <scale        android:duration="200"        android:fromXScale="0.0"        android:fromYScale="0.0"        android:pivotX="100%"        android:pivotY="0%"        android:toXScale="1.0"        android:toYScale="1.0" />    <!--        时间 0.2秒        开始全透明        结束一点都不透明    -->    <alpha        android:duration="200"        android:fromAlpha="0.0"        android:toAlpha="1.0" /></set>

popwindow_out.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@android:anim/decelerate_interpolator">    <!--        时间 0.2秒        开始的时候 x y 全是1 实际大小        结束的时候 x y 全是0 没有大小        pivotX 100% 表示最右边        pivotY 0% 表示最顶边        以上定位右上角 缩放时不变位置    -->    <scale        android:duration="200"        android:fromXScale="1.0"        android:fromYScale="1.0"        android:pivotX="100%"        android:pivotY="0%"        android:toXScale="0.0"        android:toYScale="0.0" />    <!--        时间 0.2秒        开始一点都不透明        结束全透明    -->    <alpha        android:duration="200"        android:fromAlpha="1.0"        android:toAlpha="0.0" /></set>

自定义PopupWindow

public class CustomPopupWindow extends android.widget.PopupWindow {    private Activity activity;    private View contentView;    // 用于保存PopupWindow的宽度    private int width;    // 用于保存PopupWindow的高度    private int height;    public CustomPopupWindow(Activity activity) {        super(activity);        this.activity = activity;        this.initPopupWindow();    }    private void initPopupWindow() {        LayoutInflater inflater = (LayoutInflater) activity                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);        this.contentView = inflater.inflate(R.layout.popupwindow_custom, null);        this.setContentView(contentView);        // 设置弹出窗体的宽        this.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);        // 设置弹出窗体的高        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);        // 设置弹出窗体可点击        this.setTouchable(true);        this.setFocusable(true);        // 设置点击是否消失        this.setOutsideTouchable(true);        //设置弹出窗体动画效果        this.setAnimationStyle(R.style.PopupAnimation);        //实例化一个ColorDrawable颜色为半透明        ColorDrawable background = new ColorDrawable(0x4f000000);        //设置弹出窗体的背景        this.setBackgroundDrawable(background);        // 绘制        this.mandatoryDraw();    }    /**     * 强制绘制popupWindowView,并且初始化popupWindowView的尺寸     */    private void mandatoryDraw() {        this.contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);        /**         * 强制刷新后拿到PopupWindow的宽高         */        this.width = this.contentView.getMeasuredWidth();        this.height = this.contentView.getMeasuredHeight();    }    /**     * 显示在控件的下右方     *     * @param parent parent     */    public void showAtDropDownRight(View parent) {        if (parent.getVisibility() == View.GONE) {            this.showAtLocation(parent, 0, 0, 0);        } else {            // x y            int[] location = new int[2];            //获取在整个屏幕内的绝对坐标            parent.getLocationOnScreen(location);            this.showAtLocation(parent, 0, location[0] + parent.getWidth() - this.width, location[1] + parent.getHeight());        }    }    /**     * 显示在控件的下左方     *     * @param parent parent     */    public void showAtDropDownLeft(View parent) {        if (parent.getVisibility() == View.GONE) {            this.showAtLocation(parent, 0, 0, 0);        } else {            // x y            int[] location = new int[2];            //获取在整个屏幕内的绝对坐标            parent.getLocationOnScreen(location);            this.showAtLocation(parent, 0, location[0], location[1] + parent.getHeight());        }    }    /**     * 显示在控件的下中方     *     * @param parent parent     */    public void showAtDropDownCenter(View parent) {        if (parent.getVisibility() == View.GONE) {            this.showAtLocation(parent, 0, 0, 0);        } else {            // x y            int[] location = new int[2];            //获取在整个屏幕内的绝对坐标            parent.getLocationOnScreen(location);            this.showAtLocation(parent, 0, location[0] / 2 + parent.getWidth() / 2 - this.width / 6, location[1] + parent.getHeight());        }    }    public static class PopupWindowBuilder {        private static String activityHashCode;        private static CustomPopupWindow popupWindow;        public static PopupWindowBuilder ourInstance;        public static PopupWindowBuilder getInstance(Activity activity) {            if (ourInstance == null) ourInstance = new PopupWindowBuilder();            String hashCode = String.valueOf(activity.hashCode());            /**             * 不同一个Activity             */            if (!hashCode.equals(String.valueOf(activityHashCode))) {                activityHashCode = hashCode;                popupWindow = new CustomPopupWindow(activity);            }            return ourInstance;        }        public PopupWindowBuilder setTouchable(boolean touchable) {            popupWindow.setTouchable(touchable);            return this;        }        public PopupWindowBuilder setAnimationStyle(int animationStyle) {            popupWindow.setAnimationStyle(animationStyle);            return this;        }        public PopupWindowBuilder setBackgroundDrawable(Drawable background) {            popupWindow.setBackgroundDrawable(background);            return this;        }        public CustomPopupWindow getPopupWindow() {            popupWindow.update();            return popupWindow;        }    }}

效果图

popupwindow

  相关解决方案