android自定义popupwindow动画

本文介绍如何在Android中实现自定义PopupWindow,包括如何避免获取焦点、处理点击事件、实现属性动画以及在MainActivity中的使用方法。特别强调了如何在主活动中响应Back键并执行动画后再关闭PopupWindow。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上效果图



这里的主要思想是,让popupwindow不获取焦点,然后在activity中处理各个点击事件,另外用两个属性动画来实现.请看下面代码

有哥们可能会问,不让popupwindow获取焦点会不会影响view的点击等,我下边就是使用点击事件,并且还实现了夜间模式

public class HomePopupWindowManager implements View.OnClickListener{

    public static final int DURATION_START = 200;
    public static final int DURATION_END = 200;
    private Context mContext;
    private PopupWindow pw;
    private View contentView;
    @BindView(R.id.id_ll_root)
    RelativeLayout id_ll_root;
    @BindView(R.id.id_ll_empty)
    LinearLayout id_ll_empty;
    @BindView(R.id.id_ll_content)
    LinearLayout id_ll_content;
    @BindView(R.id.id_share)
    ImageTextViewGroup id_share;
    @BindView(R.id.id_clean_cache)
    ImageTextViewGroup id_clean_cache;

    @BindView(R.id.id_add_shortcut)
    ImageTextViewGroup id_add_shortcut;
    @BindView(R.id.id_night_mode)
    ImageTextViewGroup id_night_mode;
    @BindView(R.id.id_check_update)
    ImageTextViewGroup id_check_update;
    @BindView(R.id.id_feedback)
    ImageTextViewGroup id_feedback;
    @BindView(R.id.id_about)
    ImageTextViewGroup id_about;
    @BindView(R.id.id_exit)
    ImageTextViewGroup id_exit;

    //平移的高度
    private int translationY = MetricsUtils.dip2px(180);
    private int emptyHeight = MetricsUtils.dip2px(45);
    //退出动画
    private ObjectAnimator mContentHiddrenAnim;
    private ObjectAnimator mHeadHiddrenAnim;
    //开始动画
    private ObjectAnimator mContentStartAnim;
    private ObjectAnimator mHeadStartAnim;

    public HomePopupWindowManager(Context context) {
        this.mContext = context;
        init();
        startAnim();
        exitAnim();
    }

    private void init() {
        contentView = LayoutInflater.from(mContext).inflate(R.layout.layout_home_more, null);
        ButterKnife.bind(this, contentView);
        pw = new PopupWindow(contentView, RelativeLayout.LayoutParams.MATCH_PARENT, MobileScreenUtils.getScreenHeight(mContext) - emptyHeight);
        pw.setOutsideTouchable(true);//设置点击其他区域也会消失
    }

    public void showPopupWindow(View rootView) {
        if (pw != null) {
            enterStartAnim();
            // 显示 -emptyHeight
            pw.showAtLocation(rootView, Gravity.NO_GRAVITY, 0, -emptyHeight);
        }
    }

    /**
     * 判断是否正在显示
     *
     * @return
     */
    public boolean isShow() {
        if (pw != null) {
            return pw.isShowing();
        }
        return false;
    }

    @OnClick({R.id.id_ll_empty, R.id.id_share, R.id.id_clean_cache,
            R.id.id_add_shortcut, R.id.id_night_mode, R.id.id_check_update,
            R.id.id_feedback, R.id.id_about, R.id.id_exit})
    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.id_ll_empty:
                exitStartAnim();
                break;
            case R.id.id_share:
                //分享
                break;
            case R.id.id_clean_cache:
                //清除缓存
                exitAnim();


                break;
            case R.id.id_add_shortcut:
                //添加桌面快捷方式


                break;
            case R.id.id_night_mode:
                //夜间模式
                boolean modeNight = SharedPreferencesHelper.getInstance(mContext).getBoolean(SharedPreferencesHelper.SP_KEY_MODE_NIGHT,false);
                if(modeNight){
                    //白天模式
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                    ((MainActivity)mContext).getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                    SharedPreferencesHelper.getInstance(mContext).putBoolean(SharedPreferencesHelper.SP_KEY_MODE_NIGHT,false);
                }else{
                    //使用夜间模式
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                    ((MainActivity)mContext).getDelegate().setLocalNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                    SharedPreferencesHelper.getInstance(mContext).putBoolean(SharedPreferencesHelper.SP_KEY_MODE_NIGHT,true);
                }
                ((MainActivity)mContext).recreate();
                break;
            case R.id.id_check_update:
                //检查更新

                break;
            case R.id.id_feedback:
                //意见反馈

                break;
            case R.id.id_about:
                exitStartAnim();

                break;
            case R.id.id_exit:
                exitStartAnim();
                break;
        }
    }


    /**
     * 开始退出动画
     */
    public void exitStartAnim() {
        mContentHiddrenAnim.start();
        mHeadHiddrenAnim.start();
    }

    /***
     * 开始进入动画
     */
    private void enterStartAnim() {
        mContentStartAnim.start();
        mHeadStartAnim.start();
    }

    /***
     * popupwindow进入动画
     */
    public void startAnim() {
        if (mContentStartAnim == null && mHeadStartAnim == null) {
            mContentStartAnim = ObjectAnimator.ofFloat(id_ll_content, "translationY",
                    translationY, 0);
            mHeadStartAnim = ObjectAnimator.ofFloat(id_ll_empty, "alpha", 0f, 1f);
            mContentStartAnim.setDuration(DURATION_START);
            mHeadStartAnim.setDuration(DURATION_START);
        }
    }

    /***
     * popupwindow退出动画
     */
    public void exitAnim() {
        if (mContentHiddrenAnim == null && mHeadHiddrenAnim == null) {
            mContentHiddrenAnim = ObjectAnimator.ofFloat(id_ll_content,
                    "translationY", 0, translationY);
            mHeadHiddrenAnim = ObjectAnimator.ofFloat(id_ll_empty, "alpha", 1f, 0f);
            mHeadHiddrenAnim.setDuration(DURATION_END);
            mContentHiddrenAnim.setDuration(DURATION_END);
            mContentHiddrenAnim.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    // 等待动画执行完毕关闭popupwindow
                    pw.dismiss();
                }
            });
        }
    }
}
在mainActivity中的用法如下

public class MainActivity extends BaseActivity implements View.OnClickListener {

    public static final String PATH = "https://www.baidu.com/";

    private ImageView iv_back;
    private ImageView iv_forward;
    private ImageView iv_home;
    private ImageView iv_close;
    private ImageView iv_more;

    private HomePopupWindowManager mPopupWindow;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initEvent();

    }

    private void initEvent() {
        iv_back.setOnClickListener(this);
        iv_forward.setOnClickListener(this);
        iv_home.setOnClickListener(this);
        iv_close.setOnClickListener(this);
        iv_more.setOnClickListener(this);
    }

    private void initView() {
        iv_back = (ImageView) findViewById(R.id.id_iv_back);
        iv_forward = (ImageView) findViewById(R.id.id_iv_forward);
        iv_home = (ImageView) findViewById(R.id.id_iv_home);
        iv_close = (ImageView) findViewById(R.id.id_iv_close);
        iv_more = (ImageView) findViewById(R.id.id_iv_more);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.id_iv_back:
                mPopupWindow.exitStartAnim();

                break;
            case R.id.id_iv_forward:
                mPopupWindow.exitStartAnim();

                break;
            case R.id.id_iv_home:
                mPopupWindow.exitStartAnim();

                break;
            case R.id.id_iv_close:
                mPopupWindow.exitStartAnim();

                break;
            case R.id.id_iv_more:
                if (mPopupWindow == null) {
                    mPopupWindow = new HomePopupWindowManager(MainActivity.this);
                }
                if (mPopupWindow.isShow()) {
                    mPopupWindow.exitStartAnim();
                } else {
                    mPopupWindow.showPopupWindow(v);
                }
                break;
        }
    }

    @Override
    public void onBackPressed() {
        if (mPopupWindow != null && mPopupWindow.isShow()) {
            mPopupWindow.exitStartAnim();
        } else {
            super.onBackPressed();
        }
    }
}

另外注意,当我们需要响应back键并且执行一些动画然后再关闭的时候可以使用下面方法

第一步:先不设置popupwindow的setBackgroundDrawable方法

第二步:获取popupwindow的布局文件的最外层layout,设置它的keyListener

rl_root.setOnKeyListener(new OnKeyListener() {

            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_BACK) {
                    System.out.println("获取back键");
                    //执行砸门自己的操作,等操作执行完毕之后再关闭popupwindow,这里可以使用回调
                }
                return false;
            }
        });


代码下载



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值