Android 天气APP(八)城市切换 之 自定义弹窗与使用(上)

简介: Android 天气APP(八)城市切换 之 自定义弹窗与使用(上)

自定义弹窗


既然是弹窗,那就不能让它平白无奇的出现,给一个动画效果,闪亮登场,完美谢幕。


20200404231219294.png


in_bottom_to_top.xml


<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="100%p"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toYDelta="0%p" >
</translate>


in_right_to_left.xml


<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="100%p"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toXDelta="0%p" >
</translate>


out_left_to_right.xml


<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="0%p"
    android:toXDelta="100%p"
    android:interpolator="@android:anim/accelerate_interpolator" >
</translate>


out_top_to_bottom.xml


<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromYDelta="0%p"
    android:toYDelta="100%p"
    android:interpolator="@android:anim/accelerate_interpolator" >
</translate>


然后在模块的styles.xml中增加样式


<!--弹窗样式-->
    <style name="AnimationRightFade"><!--右侧-->
        <item name="android:windowEnterAnimation">@anim/in_right_to_left</item>  <!--打开动画-->
        <item name="android:windowExitAnimation">@anim/out_left_to_right</item>  <!--关闭动画-->
    </style>
    <style name="AnimationBottomFade"><!--底部-->
        <item name="android:windowEnterAnimation">@anim/in_bottom_to_top</item>
        <item name="android:windowExitAnimation">@anim/out_top_to_bottom</item>
    </style>


然后在模块的utils包中新建一个LiWindow类


202004051607307.png


代码如下:


package com.llw.mvplibrary.utils;
import android.app.Activity;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.PopupWindow;
import com.llw.mvplibrary.R;
import java.util.HashMap;
import java.util.Map;
/**
 * 自定义弹窗
 */
public class LiWindow {
    private LiWindow mLiWindow;
    private PopupWindow mPopupWindow;
    private LayoutInflater inflater;
    private View mView;
    private Context mContext;
    private WindowManager show;
    WindowManager.LayoutParams context;
    private Map<String,Object> mMap = new HashMap<>();
    public Map<String, Object> getmMap() {
        return mMap;
    }
    public LiWindow(Context context){
        this.mContext = context;
        inflater = LayoutInflater.from(context);
        mLiWindow = this;
    }
    public LiWindow(Context context, Map<String,Object> map){
        this.mContext = context;
        this.mMap = map;
        inflater = LayoutInflater.from(context);
    }
    /**
     * 右侧显示  自适应大小
     * @param mView
     */
    public void showRightPopupWindow(View mView) {
        mPopupWindow = new PopupWindow(mView,
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT , true);
        mPopupWindow.setContentView(mView);
        mPopupWindow.setOutsideTouchable(true);//点击空白处不关闭弹窗  true为关闭
        mPopupWindow.setFocusable(true);
        mPopupWindow.setAnimationStyle(R.style.AnimationRightFade); //设置动画
        mPopupWindow.showAtLocation(mView, Gravity.RIGHT,0 ,0);
        setBackgroundAlpha(0.5f,mContext);
        WindowManager.LayoutParams nomal = ((Activity) mContext).getWindow().getAttributes();
        nomal.alpha = 0.5f;
        ((Activity) mContext).getWindow().setAttributes(nomal);
        mPopupWindow.setOnDismissListener(closeDismiss);
    }
    /**
     * 右侧显示  高度占满父布局
     * @param mView
     */
    public void showRightPopupWindowMatchParent(View mView) {
        mPopupWindow = new PopupWindow(mView,
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT , true);
        mPopupWindow.setContentView(mView);
        mPopupWindow.setOutsideTouchable(true);//点击空白处不关闭弹窗  true为关闭
        mPopupWindow.setFocusable(true);
        mPopupWindow.setAnimationStyle(R.style.AnimationRightFade); //设置动画
        mPopupWindow.showAtLocation(mView, Gravity.RIGHT,0 ,0);
        setBackgroundAlpha(0.5f,mContext);
        WindowManager.LayoutParams nomal = ((Activity) mContext).getWindow().getAttributes();
        nomal.alpha = 0.5f;
        ((Activity) mContext).getWindow().setAttributes(nomal);
        mPopupWindow.setOnDismissListener(closeDismiss);
    }
    /**
     * 底部显示
     * @param mView
     */
    public void showBottomPopupWindow(View mView) {
        mPopupWindow = new PopupWindow(mView,
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
        mPopupWindow.setContentView(mView);
        mPopupWindow.setOutsideTouchable(true);//点击空白处不关闭弹窗  true为关闭
        mPopupWindow.setFocusable(true);
        mPopupWindow.setAnimationStyle(R.style.AnimationBottomFade); //设置动画
        mPopupWindow.showAtLocation(mView, Gravity.BOTTOM, 0, 0);
        setBackgroundAlpha(0.5f,mContext);
        WindowManager.LayoutParams nomal = ((Activity) mContext).getWindow().getAttributes();
        nomal.alpha = 0.5f;
        ((Activity) mContext).getWindow().setAttributes(nomal);
        mPopupWindow.setOnDismissListener(closeDismiss);
    }
    public static void setBackgroundAlpha(float bgAlpha,Context mContext){
        WindowManager.LayoutParams lp = ((Activity) mContext).getWindow().getAttributes();
        lp.alpha = bgAlpha;
        ((Activity) mContext).getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        ((Activity) mContext).getWindow().setAttributes(lp);
    }
    /**
     * 设置弹窗动画
     * @param animId
     * @return showPopu
     */
    public LiWindow setAnim(int animId) {
        if (mPopupWindow != null) {
            mPopupWindow.setAnimationStyle(animId);
        }
        return mLiWindow;
    }
    //弹窗消失时关闭阴影
    public PopupWindow.OnDismissListener closeDismiss = new PopupWindow.OnDismissListener() {
        @Override
        public void onDismiss() {
            WindowManager.LayoutParams nomal = ((Activity)mContext).getWindow().getAttributes();
            nomal.alpha = 1f;
            ((Activity)mContext).getWindow().setAttributes(nomal);
        }
    };
    public void closePopupWindow() {
        if (mPopupWindow != null) {
            mPopupWindow.dismiss();
        }
    }
    /*
        使用方法
    *   LiWindow liWindow = new LiWindow(MainActivity.this);
        View mView = LayoutInflater.from(MainActivity.this).inflate(R.layout.center_layout,null);
        liWindow.showCenterPopupWindow(mView);
    * */
}


弹窗也是需要布局文件的,现在创建一个新的布局文件,用于显示城市列表。


返回图标:


20200405164606575.png


在项目的layout下创建一个名为window_city_list.xml的布局文件

代码如下:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:fitsSystemWindows="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <LinearLayout
        android:orientation="vertical"
        android:background="#FFF"
        android:layout_width="240dp"
        android:layout_height="match_parent">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:contentInsetLeft="16dp"
                app:popupTheme="@style/AppTheme.PopupOverlay">
                <TextView
                    android:id="@+id/tv_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:textSize="16sp"
                    android:textColor="#000"
                    android:text="中国" />
            </androidx.appcompat.widget.Toolbar>
            <!--城市列表的返回-->
            <ImageView
                android:visibility="gone"
                android:layout_marginLeft="@dimen/dp_10"
                android:layout_centerVertical="true"
                android:id="@+id/iv_back_city"
                android:src="@mipmap/icon_page_return"
                android:padding="15dp"
                android:layout_width="40dp"
                android:layout_height="40dp"/>
            <!--区/县列表的返回-->
            <ImageView
                android:visibility="gone"
                android:layout_marginLeft="@dimen/dp_10"
                android:layout_centerVertical="true"
                android:id="@+id/iv_back_area"
                android:src="@mipmap/icon_page_return"
                android:padding="15dp"
                android:layout_width="40dp"
                android:layout_height="40dp"/>
        </RelativeLayout>
        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:background="#EEEEEE"/>
        <!--数据展示-->
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>
</RelativeLayout>


为了让点击的时候有一个效果,在模块的res文件下的drawable下创建一个rounded_corners.xml的样式文件,点击的水波纹效果


20200405165319861.png


代码如下


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#18ffc400"/>
        </shape>
    </item>
    <item android:state_focused="true" android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="#0f000000"/>
        </shape>
    </item>
</selector>


接下来在res文件下下新建一个drawable-v21的文件夹,文件夹下创建一个


bg_white.xml


20200405165514119.png


代码如下:


<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#20000000"
    android:drawable="@drawable/rounded_corners"/>


点击的样式做好了,接下来创建城市列表的item


在项目的layout文件夹下创建一个名为item_city_list.xml的布局文件


20200405165728527.png


代码如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_city"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFF"
    android:orientation="vertical">
    <!--显示省 、 市 、 区/县-->
    <TextView
        android:id="@+id/tv_city"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foreground="@drawable/bg_white"
        android:gravity="center"
        android:padding="10dp"
        android:textColor="#FF000000"
        android:textSize="15sp" />
    <!--分隔线-->
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:background="#EEEEEE"/>
</LinearLayout>


接下来就是要创建一个实体Bean用来接收JSON中解析出来的城市数据,里面包含了省、市、区/县


在项目的bean包下新建一个CityResponse


20200405170253561.png


代码如下:


package com.llw.goodweather.bean;
import java.util.List;
public class CityResponse {
    /**
     * name : 北京市
     * city : [{"name":"北京市","area":["东城区","西城区","崇文区","宣武区","朝阳区","丰台区","石景山区","海淀区","门头沟区","房山区","通州区","顺义区","昌平区","大兴区","平谷区","怀柔区","密云县","延庆县"]}]
     */
    private String name;
    private List<CityBean> city;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<CityBean> getCity() {
        return city;
    }
    public void setCity(List<CityBean> city) {
        this.city = city;
    }
    public static class CityBean {
        /**
         * name : 北京市
         * area : ["东城区","西城区","崇文区","宣武区","朝阳区","丰台区","石景山区","海淀区","门头沟区","房山区","通州区","顺义区","昌平区","大兴区","平谷区","怀柔区","密云县","延庆县"]
         */
        private String name;
        private List<AreaBean> area;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public static class AreaBean {
            /**
             * name : 北京市
             * area : ["东城区","西城区","崇文区","宣武区","朝阳区","丰台区","石景山区","海淀区","门头沟区","房山区","通州区","顺义区","昌平区","大兴区","平谷区","怀柔区","密云县","延庆县"]
             */
            private String name;
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
        }
    }
}


接下来创建适配器,需要三个适配器,省、市、区/县。在adapter包下创建


ProvinceAdapterCityAdapterAreaAdapter


20200405171755476.png


ProvinceAdapter.java


package com.llw.goodweather.adapter;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.CityResponse;
import java.util.List;
/**
 * 省列表适配器
 */
public class ProvinceAdapter extends BaseQuickAdapter<CityResponse, BaseViewHolder> {
    public ProvinceAdapter(int layoutResId, @Nullable List<CityResponse> data) {
        super(layoutResId, data);
    }
    @Override
    protected void convert(BaseViewHolder helper, CityResponse item) {
        helper.setText(R.id.tv_city,item.getName());//省名称
        helper.addOnClickListener(R.id.item_city);//点击之后进入市级列表
    }
}


CityAdapter.java


package com.llw.goodweather.adapter;
import androidx.annotation.Nullable;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.llw.goodweather.R;
import com.llw.goodweather.bean.CityResponse;
import java.util.List;
/**
 * 市列表适配器
 */
public class CityAdapter extends BaseQuickAdapter<CityResponse.CityBean, BaseViewHolder> {
    public CityAdapter(int layoutResId, @Nullable List<CityResponse.CityBean> data) {
        super(layoutResId, data);
    }
    @Override
    protected void convert(BaseViewHolder helper, CityResponse.CityBean item) {
        helper.setText(R.id.tv_city,item.getName());//市名称
        helper.addOnClickListener(R.id.item_city);//点击事件  点击进入区/县列表
    }
}
相关文章
|
1月前
|
XML Java 数据库
安卓项目:app注册/登录界面设计
本文介绍了如何设计一个Android应用的注册/登录界面,包括布局文件的创建、登录和注册逻辑的实现,以及运行效果的展示。
140 0
安卓项目:app注册/登录界面设计
|
1月前
|
移动开发 小程序 测试技术
自定义多级联动选择器指南(uni-app)
在本文中,探讨了如何在uni-app中创建自定义多级联动选择器组件。这个组件具有强大的多端支持,可适用于H5、APP、微信小程序、支付宝小程序等多种平台。
33 1
自定义多级联动选择器指南(uni-app)
|
1月前
|
JavaScript 前端开发 UED
Vue与uni-app开发中通过@font-face巧妙引入自定义字体
Vue与uni-app开发中通过@font-face巧妙引入自定义字体
71 9
|
1月前
|
安全 网络安全 Android开发
深度解析:利用Universal Links与Android App Links实现无缝网页至应用跳转的安全考量
【10月更文挑战第2天】在移动互联网时代,用户经常需要从网页无缝跳转到移动应用中。这种跳转不仅需要提供流畅的用户体验,还要确保安全性。本文将深入探讨如何利用Universal Links(仅限于iOS)和Android App Links技术实现这一目标,并分析其安全性。
222 0
|
2月前
|
XML 数据库 Android开发
10分钟手把手教你用Android手撸一个简易的个人记账App
该文章提供了使用Android Studio从零开始创建一个简单的个人记账应用的详细步骤,包括项目搭建、界面设计、数据库处理及各功能模块的实现方法。
|
缓存 开发工具 Android开发
Android App性能评测分析-启动时间篇
1、前言 随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,性能问题从应用的启动优化开始,下面会根据实际app性能测试案例,进行app性能评测之启动时间的分析和总结。
4265 0
|
Shell Linux 测试技术
Android App性能评测分析-cpu占用篇
1、前言 很多时候在使用APP的时候,手机可能会发热发烫。这是因为CPU使用率过高,CPU过于繁忙,会使整个手机无法响应用户,整体性能降低,用户体验就会很差,也容易引起ANR等等一系列问题。
5182 0
|
Java 测试技术 程序员
Android App性能评测分析-内存篇
1、内存了解 在Android App的性能优化的各个部分里,内存方面的知识较多且不易理解,内存的问题绝对是最令人头疼的一部分,需要对内存基础知识、内存分配、内存管理机制等非常熟悉,才能排查问题。
2237 0
|
缓存 网络协议 测试技术
Android App性能评测分析-网络流量篇
1、 前言 移动互联网发展到现在,虽然用户的联网方式已经完成了3G/4G网络依赖到Wifi依赖的转变,但是过多以及没有经过处理的网络请求,会消耗用户的网络流量,造成用户流量费用(金钱)的损失,高流量的消耗必然导致非WIFI场景用户的流失,流量测试在性能评测中势必会占较大的权重。
3337 0
|
1月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
476 7

热门文章

最新文章