自定义弹窗
既然是弹窗,那就不能让它平白无奇的出现,给一个动画效果,闪亮登场,完美谢幕。
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类
代码如下:
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); * */ }
弹窗也是需要布局文件的,现在创建一个新的布局文件,用于显示城市列表。
返回图标:
在项目的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的样式文件,点击的水波纹效果
代码如下
<?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
代码如下:
<?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的布局文件
代码如下:
<?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
代码如下:
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包下创建
ProvinceAdapter、CityAdapter、AreaAdapter
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);//点击事件 点击进入区/县列表 } }