根据项目需求了一个从底部弹出的PopupWindow,它的作用是选择地址的。省份,市,区都在同一个里面,同时选择。先上效果图。
一、思路
1、用一个ListView加载这三个部分的数据,在切换的时候,直接切换数据选择。
2、选完某个地址时,对外提供一个回调事件,比如在省份选择后,则应该查询对应的城市,这时候是要对外提供接口,查询到城市的数据后,再切换到城市的选择。
3、一个从底部弹出的popupwindow的实现。
二、代码实现
1、在构造方法里,初始化popupWindow,需要继承PopupWindow
public MyPopupWindow(final Activity activity, final View parent,
List<String> provinces) {
this.activity = activity;
this.provinces = provinces;
citys = new ArrayList<String>();
districts =new ArrayList<String>();
view = LayoutInflater.from(activity).inflate(R.layout.my_pop, null);
//透明度
view.startAnimation(AnimationUtils.loadAnimation(activity,R.anim.fade_ins));
//从下往上出现
view.startAnimation(AnimationUtils.loadAnimation(activity,
R.anim.push_bottom_in));
//设置它的宽高
setWidth(LayoutParams.MATCH_PARENT);
setHeight(LayoutParams.WRAP_CONTENT);
// 实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0xb0000000);
// 设置SelectPicPopupWindow弹出窗体的背景
this.setBackgroundDrawable(dw);
setFocusable(true);
setOutsideTouchable(true);
setContentView(view);
initView();
initListener();
initData();
}
2、点击其他区域,取消popupview。
这部分代码是放在initListener();方法里面,单独抽出来的。取消它的时候同时在setOnDismissListener()里改变Activity的透明度。
view.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int y = (int) event.getY();
// 没有点击到布局的区域
if (isShowing()) {
if (ll_content != null) {
if (y < getScreenHeight()
- (ll_content.getHeight() + 50)) {
dismiss();
}
} else {
if (y < getScreenHeight() - (view.getHeight() + 50)) {
dismiss();
}
}
}
break;
default:
break;
}
return true;
}
});
setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss() {
params = activity.getWindow().getAttributes();
params.alpha = 1f;
activity.getWindow().setAttributes(params);
}
});
3、对外提供更新数据的接口
共3个接口,主要是对外提供选中的数据,同时获取对应的地区的数据,让用户进行下一步的选择。
/**
* @author Lenovo
*选择省份后回调事件,这时候就要查询省份,对应的城市,需要自行保存省份的值,之后不在传
*/
public interface SelectProvince{
/**param 选中的省份*/
public void onSelectProvince(String province,MyAdapter myAdapter);
}
/**
* @author Lenovo
*选择城市后回调事件,这时候要查询城市对应的地区,需要自行保存城市的值,之后不在传
*/
public interface SelectCity{
public void onSelectCity(String city,MyAdapter myAdapter);
}
/**
* @author Lenovo
*选择地区后回调事件
*/
public interface SelectDistrict{
public void onSelectDistrict(String district,MyAdapter myAdapter);
}
4、设置Listview的点击事件,并调用上面的接口。
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view, int pos,
long id) {
if(currentPos==0){//省份
provinceSelected = pos;
citySelected = 0;
districtSelected = 0;
tv_city.setVisibility(View.VISIBLE);
showLine(1);
if(selectProvince!=null){
//回调事件1
selectProvince.onSelectProvince(provinces.get(pos),myAdapter);
}
tv_province.setText(provinces.get(pos));
}else if(currentPos==1){//市区
citySelected = pos;
districtSelected = 0;
tv_district.setVisibility(View.VISIBLE);
showLine(2);
if(selectCity!=null){
//回调事件2
selectCity.onSelectCity(citys.get(pos), myAdapter);
}
tv_city.setText(citys.get(pos).toString());
}else if(currentPos==2){//区域
districtSelected = pos;
if(selectDistrict!=null){
//回调事件3
selectDistrict.onSelectDistrict(districts.get(pos).toString(), myAdapter);
}
tv_district.setText(districts.get(pos).toString());
//选完区域后结束
dismiss();
}
}
});
5、实现透明度、从下往上的动画。
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="20"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:fromYDelta="100%"
android:interpolator="@android:anim/decelerate_interpolator"
android:toYDelta="0" />
6、显示PopupWindow
要设置外部Activity的透明度,如下代码。
public void showPopupWindow(View parent){
params = activity.getWindow().getAttributes();
params.alpha = 0.7f;
activity.getWindow().setAttributes(params);
showAtLocation(parent, Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);
}
7、外部Activity调用PopupWindow
主要是实现PopupWindow 所提供的三个接口
pop = new MyPopupWindow(this, content, provinces);
pop.setSelectProvinceListener(new SelectProvince() {
@Override
public void onSelectProvince(String province, MyAdapter myAdapter) {
area = province;
bt1.setText(area);
//查询对应的城市
pop.setCitys(citys);
myAdapter.setDatas(citys);
myAdapter.notifyDataSetChanged();
}
});
pop.setSelectCityListener(new SelectCity() {
@Override
public void onSelectCity(String city, MyAdapter myAdapter) {
area += city;
bt1.setText(area);
//查询对应的区
pop.setDistricts(districts);
myAdapter.setDatas(districts);
myAdapter.notifyDataSetChanged();
}
});
pop.setSelectDistrictListener(new SelectDistrict() {
@Override
public void onSelectDistrict(String district, MyAdapter myAdapter) {
area += district;
bt1.setText(area);
}
});
8、其它的一下方法
/**
* 获取屏幕高度
*
* @return
*/
public int getScreenHeight() {
int screenHeight = 0;
DisplayMetrics dm = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
if (dm != null) {
int screenWidth = dm.widthPixels;// 屏幕宽度
int height = dm.heightPixels;// 全屏幕高度
int statusBarHeight = getStatusBarHeight(activity);// 状态栏高度
screenHeight = height - statusBarHeight;// 屏幕高度
}
return screenHeight;
}
/**
* 获取状态栏高度
*
* @param activity
* @return
*/
public int getStatusBarHeight(Activity activity) {
int result = 0;
int resourceId = activity.getResources().getIdentifier(
"status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = activity.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
三、总结
总体上实现这个控件还是比较简单的,主要是比较繁琐而已,其它的一些基础代码如布局文件,适配器等就不贴出来了。