底部弹出PopupWindow+地址三级联动,多问题全面分析,详细注释

简介: 底部弹出PopupWindow+地址三级联动,多问题全面分析,详细注释

主要功能:从底部弹出的 PopupWindow,带动画,带灰色背景,在PopupWindow中实现省市区三级联动,并填充textview

image.png

先看效果图


1.PopupWindow


<span style="font-size:18px;">public class PopHelper {
    private Context mContext;
    private PopupWindow pw;
    private CityPicker cityPicker;
    public PopHelper(Context context) {
        mContext = context;
    }
    /**
     * @param view
     * @param itemsOnClick 抛出一个OnClickListener接口
     */
    public void showAddressPop(View view, final Activity activity, View.OnClickListener itemsOnClick) {
        // 设置pw里的点击事件
        LinearLayout addressView = (LinearLayout) View.inflate(mContext, R.layout.pop_address, null);
        Button btnPopAddressCencel = (Button) addressView.findViewById(R.id.btn_pop_address_cencel);
        btnPopAddressCencel.setOnClickListener(itemsOnClick);
        Button btnPopAddressEnter = (Button) addressView.findViewById(R.id.btn_pop_address_enter);
        btnPopAddressEnter.setOnClickListener(itemsOnClick);
        cityPicker = (CityPicker) addressView.findViewById(R.id.citypicker);
        //-2是包裹自己,-1是填充父容器
        pw = new PopupWindow(addressView, -1, -2);
        //先关闭
        colsePopupwindow();
        //必须要设置一个背景
        pw.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        //点击外边可关闭pw
        pw.setOutsideTouchable(true);
        //pw内可获取焦点
        pw.setFocusable(true);
        // 设置背景颜色变暗
        WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
        lp.alpha = 0.7f;
        activity.getWindow().setAttributes(lp);
        //退出时恢复透明度
        pw.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
                lp.alpha = 1f;
                activity.getWindow().setAttributes(lp);
            }
        });
        //设置动画
        pw.setAnimationStyle(R.style.take_photo_anim);
        //显示。y轴距离底部100是因为部分手机有虚拟按键,所以实际项目中要动态设置
        pw.showAtLocation(view, Gravity.BOTTOM, 0, 100);
    }
    /**
     *
     * @return 获取控件中的地址数据
     */
    public String getAddressData() {
        String cData = cityPicker.getCity_string();
        return cData;
    }
    /**
     * 关闭pw
     */
    public void colsePopupwindow() {
        if (pw != null && pw.isShowing()) {
            pw.dismiss();
            pw = null;
        }
    }
}</span>

2.pop的弹出退出动画

pop_enter_anim.xml
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
  <translate 
    android:duration="200" 
    android:fromYDelta="100%p" 
    android:toYDelta="0" /> 
  <alpha 
    android:duration="200" 
    android:fromAlpha="0.0" 
    android:toAlpha="1.0" /> 
</set></span>
pop_exit_anim.xml
<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"> 
  <translate 
    android:duration="200" 
    android:fromYDelta="0" 
    android:toYDelta="50%p" /> 
  <alpha 
    android:duration="200" 
    android:fromAlpha="1.0" 
    android:toAlpha="0.0" /> 
</set> </span>

记得copy  styles文件中的style


3.在MainActivity中的调用

<span style="font-size:18px;">public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView textView1, textView2;
    private Button button1, button2;
    private PopHelper popHelper;//pop
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView1 = (TextView) findViewById(R.id.textView1);
        textView2 = (TextView) findViewById(R.id.textView2);
        button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(this);
        button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(this);
    }
    /**
     * 实现popHelper中的item接口
     */
    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_pop_address_cencel:
                    popHelper.colsePopupwindow();
                    break;
                case R.id.btn_pop_address_enter:
                    String addressData = popHelper.getAddressData();
                    if (flag) {
                        textView1.setText(addressData);
                    } else {
                        textView2.setText(addressData);
                    }
                    popHelper.colsePopupwindow();
                    break;
            }
        }
    };
    boolean flag;//用于pop标记显示,避免多个地方显示却只填充一个textview的情况
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
                popHelper = new PopHelper(getApplicationContext());
                popHelper.showAddressPop(v, MainActivity.this, onClickListener);
                flag = true;
                break;
            case R.id.button2:
                popHelper = new PopHelper(getApplicationContext());
                popHelper.showAddressPop(v, MainActivity.this, onClickListener);
                flag = false;
                break;
        }
    }
}</span>

4.地址三级联动

首先,在main目录下创建assets文件,并copy城市json数据包


其次,在lib中加入gson包,记得As a lib,或直接


<span style="font-size:18px;">compile 'com.google.code.gson:gson:2.6.2'</span>

然后,修改布局中的控件名称换成自己的包名+自定义类名

最后在values文件夹中copy-attrs.xml文件

然后就完美实现了。


代码中都有详细注释


目录
相关文章
|
XML Android开发 数据安全/隐私保护
10. 【Android教程】网格布局 GridLayout
10. 【Android教程】网格布局 GridLayout
610 1
|
Web App开发 前端开发 JavaScript
浏览器的历史和主要组成部分
浏览器的历史可以追溯到1991年8月,当时 Berners-Lee 发明了 World Wide Web 万维网,同时也带来了世上第一款浏览器,但这款浏览器的名字比较长,他索性将其改名为`Nexus`
|
Python
数学建模——统计回归模型
数学建模——统计回归模型
678 0
|
12月前
|
机器学习/深度学习 编解码 人工智能
扩散模型失宠?端侧非自回归图像生成基础模型Meissonic登场,超越SDXL!
Meissonic是一种新型图像生成模型,采用非自回归的掩码图像建模(MIM)方法,在性能和效率上超越了当前最先进的扩散模型SDXL。其创新点包括改进的注意力机制、多尺度特征提取、先进位置编码策略和优化采样条件等,能够生成高质量、高分辨率图像。此外,Meissonic引入人类偏好评分和特征压缩层,提升图像质量和计算效率。尽管存在一些挑战,Meissonic为统一语言-视觉模型的发展提供了新思路,并在创意设计、虚拟现实等领域展现出广泛应用前景。
259 24
|
开发工具 数据安全/隐私保护
【Azure Developer】使用MSAL4J 与 ADAL4J 的SDK时候,遇见了类型冲突问题 "java.util.Collections$SingletonList cannot be cast to java.lang.String"
【Azure Developer】使用MSAL4J 与 ADAL4J 的SDK时候,遇见了类型冲突问题 "java.util.Collections$SingletonList cannot be cast to java.lang.String"
299 0
|
JSON 前端开发 Java
【Java笔记+踩坑】SpringMVC基础
springmvc简介、入门案例、bean加载控制、PostMan工具的使用、普通和JSON和日期格式请求参数传递、响应JSON或jsp或文本、Rest风格
【Java笔记+踩坑】SpringMVC基础
|
监控 前端开发 JavaScript
|
关系型数据库 分布式数据库 数据库
PolarDB 数据库迁移工具与策略
【8月更文第27天】随着业务的增长和技术的发展,企业常常需要对现有的数据库进行升级或迁移以适应新的需求。阿里云提供的 PolarDB 是一款高性能的关系型数据库服务,支持 MySQL、PostgreSQL 和 Oracle 三种存储引擎。本文将介绍如何利用 PolarDB 提供的迁移工具来高效地完成数据迁移工作,并探讨在迁移过程中需要注意的关键点。
950 0
|
测试技术 运维
并发模式与 RPS 模式之争,性能压测领域的星球大战
本文是《如何做好性能压测》系列专题分享的第四期,该专题将从性能压测的设计、实现、执行、监控、问题定位和分析、应用场景等多个纬度对性能压测的全过程进行拆解,以帮助大家构建完整的性能压测的理论体系,并提供有例可依的实战。
13293 105