Android-PopupWindow

Android PopupWindow 的使用非常广泛,PopupWindow的特点是悬浮在Activity之上的,PopupWindow可以悬浮在Activity的指定位置(X/Y);

PopupWindow 要显示的View,可以用布局加载器 加载自定义的布局文件,也可以加载 new ListView(),等等,非常的灵活

PopupWindow的使用:

package liudeli.ui.all;

import android.app.Activity;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class PopupActivity extends Activity {

    private final String TAG = PopupActivity.class.getSimpleName();

    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_popup);

        // 初始化ListView
        listView = new ListView(this);
    }

    // 定义popupWindow
    private PopupWindow popupWindow;

    /**
     * 弹出popup
     * @param view
     */
    public void startPopup(View view) {

        /**
         * 真实开发中,初始化数据要写在onCreate()方法
         * 我写在这里是为了代码好区分
         */
        // 模拟数据
        final List<String> listData = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            listData.add("测试数据" + i + 1);
        }

        // 既然是数组简单类型的数据,就是用ArrayAdapter
        ListAdapter adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                android.R.id.text1,
                listData);

        // 把数据绑定给ListView
        listView.setAdapter(adapter);

        // 设置ListView条目点击事件监听
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String item = listData.get(position);
                Toast.makeText(PopupActivity.this, "" + item, Toast.LENGTH_SHORT).show();

                // 关闭popupWindow
                if (null != popupWindow) popupWindow.dismiss();
            }
        });

        if (null == popupWindow) {
            popupWindow = new PopupWindow();
            // 设置popupWindow宽度
            popupWindow.setWidth(360);
            // 设置popupWindow高度
            // popupWindow.setHeight(200);
            popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
            // 设置popupWindow焦点
            popupWindow.setFocusable(true);
            // 设置popupWindow去加载的ListView
            popupWindow.setContentView(listView);
            // 设置监听
            popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    Toast.makeText(PopupActivity.this, "popupWindow被关闭了", Toast.LENGTH_SHORT).show();
                }
            });
        }
        // 参数一:在那个控件旁边弹出
        // 参数二:距离控件X轴相关距离设置
        // 参数三:距离控件Y轴相关距离设置
        popupWindow.showAsDropDown(view, 0, 0);
    }


    // 定义popupWindow
    private PopupWindow popupWindow2;

    /**
     * 弹出popup 带动画
     * @param view
     */
    public void startPopup2(View view) {
        /**
         * 真实开发中,初始化数据要写在onCreate()方法
         * 我写在这里是为了代码好区分
         */
        // 模拟数据
        final List<String> listData = new ArrayList<>();
        for (int i = 2008; i < 2018; i++) {
            listData.add("" + i + 1);
        }

        // 既然是数组简单类型的数据,就是用ArrayAdapter
        ListAdapter adapter = new ArrayAdapter<String>(this,
                R.layout.popup_item,
                R.id.tv_year,
                listData);

        // 把数据绑定给ListView
        listView.setAdapter(adapter);

        // 设置ListView条目点击事件监听
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String item = listData.get(position);
                Toast.makeText(PopupActivity.this, "" + item, Toast.LENGTH_SHORT).show();

                // 点击条目后,关闭popupWindow
                if (null != popupWindow2) popupWindow2.dismiss();
            }
        });

        if (null == popupWindow2) {

            // 参数一:设置popupWindow去加载的ListView
            // 参数二:设置PopupWindow宽度
            // 参数三:设置PopupWindow高度,自动包裹,数据多大,我就多大
            popupWindow2 = new PopupWindow(listView, dp2px(80), ViewGroup.LayoutParams.WRAP_CONTENT);

            // 设置popupWindow焦点
            popupWindow2.setFocusable(true);

            // 设置监听
            popupWindow2.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    Toast.makeText(PopupActivity.this, "popupWindow2被关闭了", Toast.LENGTH_SHORT).show();
                }
            });

            // 设置动画
            popupWindow2.setAnimationStyle(R.style.AnimationFade);
        }

        // 参数一:在那个控件旁边弹出
        // 参数二:距离控件X轴相关距离设置
        // 参数三:距离控件Y轴相关距离设置
        popupWindow2.showAsDropDown(view, 65, 10);
    }

    private PopupWindow popupWindow3;

    /**
     * 测试popup,测试如下:
     *                   1.setContentView(随意写的布局);
     *
     * @param view
     */
    public void testPopup(View view) {
        if (null == popupWindow3) {
            // 使用布局加载器,去加载一个布局
            View popupLogin = LayoutInflater.from(this).inflate(R.layout.popup_login, null);

            // 创建PopupWindow
            popupWindow3 = new PopupWindow();

            /**
             * 设置PopupWindow要加载的View
             * 这里的setContentView和Activity的setContentView很相似
             */
            popupWindow3.setContentView(popupLogin);

            // 设置PopupWindow显示的宽度
            popupWindow3.setWidth(dp2px(300));

            // 设置PopupWindow显示的高度
            popupWindow3.setHeight(dp2px(300));

            // 设置popupWindow焦点
            /*popupWindow3.setFocusable(true);
            popupWindow3.setOutsideTouchable(true);*/

            /**
             * android popupwindow 点击外部消失
             * 必须是在定义好popwindow3后,在ShowAtLocation方法调用之前加上
             */
            popupWindow3.setBackgroundDrawable(new BitmapDrawable());
            popupWindow3.setFocusable(true);
            popupWindow3.setOutsideTouchable(true);
            popupWindow3.update();

            // 监听Popup被关闭
            popupWindow3.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    Toast.makeText(PopupActivity.this, "popupWindow3被关闭了", Toast.LENGTH_SHORT).show();
                    /**
                     * 恢复Activity背景透明度
                     */
                    backgroundAlpha(1f);
                }
            });

            // 设置动画效果
            popupWindow3.setAnimationStyle(R.style.AnimationFade);

            // setContentView的 popup_login 的 用户名EditText
            final EditText etName = popupLogin.findViewById(R.id.et_name);

            // setContentView的 popup_login 的 密码EditText
            final EditText etPwd = popupLogin.findViewById(R.id.et_pwd);

            // setContentView的 popup_login 的 登录按钮
            popupLogin.findViewById(R.id.bt_login).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (TextUtils.isEmpty(etName.getText().toString()) || TextUtils.isEmpty(etPwd.getText().toString())) {
                        Toast.makeText(PopupActivity.this, "请输入用户名和密码", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    if ("abc".equals(etName.getText().toString().trim()) && "123".equals(etPwd.getText().toString().trim())) {
                        Toast.makeText(PopupActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
                        popupWindow3.dismiss();
                    } else {
                        Toast.makeText(PopupActivity.this, "密码或用户名错误", Toast.LENGTH_SHORT).show();
                    }
                }
            });

            //监听popupWindow3触屏事件,只要碰摸到popupWindow3,就会触发
            /*popupWindow3.setTouchInterceptor(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (popupWindow3 != null && popupWindow3.isShowing()) {
                        popupWindow3.dismiss();
                    }
                    return false;
                }
            });*/
        }
        // 参数一:在那个控件旁边弹出
        // 参数二:距离控件X轴相关距离设置
        // 参数三:距离控件Y轴相关距离设置
        popupWindow3.showAsDropDown(view, -100, 100);

        /**
         * Android中popupwindow弹出后,控制屏幕背景的透明效果,
         * 可以设置一下getWindows的透明度。backgroundAlpha(0.5f);
         */
        backgroundAlpha(0.5f);
    }

    /**
     * 设置popupwindow外面背景透明度
     * @param bgalpha 透明度  0-1   0-透明   1-不透明
     */
    private void backgroundAlpha(float bgalpha) {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.alpha = bgalpha;
        getWindow().setAttributes(lp);
    }

    /***
     *  在Java代码中必须要 dp px 转换
     */
    private int dp2px(int dp){
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,getResources().getDisplayMetrics());
    }
}

Activity引用的布局文件:activity_popup.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="弹出popup"
        android:onClick="startPopup"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="弹出popup带动画"
        android:onClick="startPopup2"
        android:layout_alignParentRight="true"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="49dp"
        android:text="测试popup"
        android:onClick="testPopup"
        />

</RelativeLayout>

values/styles.xml定义的动画:

  <!-- PopupWindow动画 -->
    <style name="AnimationFade">
        <!-- PopupWindow左右弹出的效果 -->
        <item name="android:windowEnterAnimation">@anim/inputodown</item>
        <item name="android:windowExitAnimation">@anim/outdowntoup</item>
    </style>

anim/的两个动画文件 inputodown.xml   outdowntoup.xml

inputodown.xml:

<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="500"
        android:fromYDelta="-100%"
        android:toYDelta="0" />

</set>

outdowntoup.xml:

<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <translate
        android:duration="500"
        android:fromYDelta="0"
        android:toYDelta="-100%" />

</set>

popupWindow2---> ListView --- > 适配器用到的 Item 布局:popup_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_year"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="2019"
        android:paddingRight="6dp"
        android:paddingLeft="6dp"
        android:paddingTop="8dp"
        android:paddingBottom="8dp"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

popupWindow setContent 用到的布局文件 popup_login.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/white">

    <!--
        注意以下属性可以解决:EditText 在PopupWindow EditText无法获取焦点的问题
        android:windowSoftInputMode="adjustPan|stateHidden"
    -->
    <EditText
        android:id="@+id/et_name"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:hint="请输入用户名"
        android:layout_gravity="center"
        android:layout_margin="10dp"
        android:windowSoftInputMode="adjustPan|stateHidden"
        />

    <!--
        注意以下属性可以解决:EditText 在PopupWindow EditText无法获取焦点的问题
        android:windowSoftInputMode="adjustPan|stateHidden"
    -->
    <EditText
        android:id="@+id/et_pwd"
        android:layout_width="200dp"
        android:layout_height="40dp"
        android:hint="请输入密码"
        android:layout_gravity="center"
        android:layout_margin="10dp"
        android:inputType="textPassword"
        android:windowSoftInputMode="adjustPan|stateHidden"
        />

    <Button
        android:id="@+id/bt_login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="登录"
        android:layout_gravity="center"
        android:layout_margin="10dp"
        />

</LinearLayout>

效果图:

原文地址:https://www.cnblogs.com/android-deli/p/10154273.html