Android 使用PopupWindow实现下拉列表

时间:2020-12-21 10:13:20

来看效果图:

Android 使用PopupWindow实现下拉列表

在实现这个效果前,先来了解下PopupWindow的常用方法

构造方法

在实例化PopupWindow窗口时,需要我们自己传入窗口的界面视图和窗口的尺寸
实例化PopupWindow的方法常用以下几种

public PopupWindow(View contentView)
public PopupWindow(int width, int height)
public PopupWindow(View contentView, int width, int height)
public PopupWindow(View contentView, int width, int height, boolean focusable)

在PopupWindow中,并没有像AlertDialog一样是有个默认的布局,所以实例化PopupWindow时我们就必须给它设置一个布局,和指定他的宽高,这三个少一个都不能正常弹出PopupWindow

显示方法

常用的显示方法:

// 相对view控件的位置,位于view控件正下方
public void showAsDropDown(View anchor)
// 相对view控件的位置,可设置偏移值
public void showAsDropDown(View anchor, int xoff, int yoff)
// 相对于整个窗口的位置
public void showAtLocation(View parent, int gravity, int x, int y)

第一个方法showAsDropDown:
指定需要在哪个View控件下显示窗口就好,默认popupWindow窗口的左上角对齐view控件的左下角。
第二个方法showAsDropDown:
xoff和yoff两个值分别设置popup窗口的横向和竖直方向上的偏移值
xoff为负数时窗口向左偏移,为正数时窗口向右偏移
同理yoff为负数时窗口向上偏移,为正数时向下偏移
第三个方法showAtLocation:
parent参数只要传进当前窗口上有的任意一个View控件就好,不要被parent这个单词的字面意思给搞混了,并不是需要传ViewGroup对象。
gravity参数需要我们传递一个Gravity值,可以指定一个或者多个属性,如:Gravity.RIGHT|Gravity.BOTTOM
最后两个参数x、y为两个偏移值,和showAsDropDown偏移值的处理方式一致

常用方法

// popup窗口显示状态,显示则返回true
public boolean isShowing()

// 设置popup窗口是否具有获取焦点的能力
public void setFocusable(boolean focusable)

// 设置是否响应touch点击事件
public void setTouchable(boolean touchable)

// 设置点击窗口外边是否可让popup窗口消失
public void setOutsideTouchable(boolean touchable)

// 设置popup窗口背景图片,这个方法挺重要的,查看源码可以发现
// 加上它后,setOutsideTouchable()方法才能生效
// 加上它后,按手机返回键关闭popup窗口的功能才会生效
public void setBackgroundDrawable(Drawable background)

// 设置popup窗口关闭事件的监听
public void setOnDismissListener(OnDismissListener onDismissListener)

// 关闭popup窗口
public void dismiss()

实现上图中的效果
这里用的是一个TextView控件,也可以换成EditText控件,一样的效果

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:background="#737373"
android:gravity="center"
android:orientation="vertical">


<TextView
android:id="@+id/tv_select_input"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:background="@drawable/bg_filter_down"
android:drawableRight="@drawable/ic_arrows_down"
android:gravity="center"
android:padding="10dp"
android:textSize="12sp" />


</LinearLayout>

TextView控件的背景图片bg_filter_down.xml,和popupWindw窗口的布局文件bg_corner.xml是一样的

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--设置背景颜色-->
<solid android:color="#ffffff" />
<!-- 设置圆角角度 -->
<corners android:radius="5dp" />
</shape>

那个小箭头图片ic_arrows_down可以自己找个图片设置上去,也可以不加。

主要代码

/**
* 主界面
* Created by zhuwentao on 2016-08-10.
*/

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

/** TextView选择框 */
private TextView mSelectTv;

/** popup窗口里的ListView */
private ListView mTypeLv;

/** popup窗口 */
private PopupWindow typeSelectPopup;

/** 模拟的假数据 */
private List<String> testData;

/** 数据适配器 */
private ArrayAdapter<String> testDataAdapter;

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

/**
* 初始化UI
*/

private void initUI() {
mSelectTv = (TextView) findViewById(R.id.tv_select_input);
}

/**
* 初始化监听
*/

private void initListener() {
mSelectTv.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_select_input:
// 点击控件后显示popup窗口
initSelectPopup();
// 使用isShowing()检查popup窗口是否在显示状态
if (typeSelectPopup != null && !typeSelectPopup.isShowing()) {
typeSelectPopup.showAsDropDown(mSelectTv, 0, 10);
}
break;
}
}

/**
* 初始化popup窗口
*/

private void initSelectPopup() {
mTypeLv = new ListView(this);
TestData();
// 设置适配器
testDataAdapter = new ArrayAdapter<String>(this, R.layout.popup_text_item, testData);
mTypeLv.setAdapter(testDataAdapter);

// 设置ListView点击事件监听
mTypeLv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 在这里获取item数据
String value = testData.get(position);
// 把选择的数据展示对应的TextView上
mSelectTv.setText(value);
// 选择完后关闭popup窗口
typeSelectPopup.dismiss();
}
});
typeSelectPopup = new PopupWindow(mTypeLv, mSelectTv.getWidth(), ActionBar.LayoutParams.WRAP_CONTENT, true);
// 取得popup窗口的背景图片
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.bg_corner);
typeSelectPopup.setBackgroundDrawable(drawable);
typeSelectPopup.setFocusable(true);
typeSelectPopup.setOutsideTouchable(true);
typeSelectPopup.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
// 关闭popup窗口
typeSelectPopup.dismiss();
}
});
}

/**
* 模拟假数据
*/

private void TestData() {
testData = new ArrayList<>();
for (int i = 0; i < 10; i++) {
String str = new String("数据" + i);
testData.add(str);
}
}
}

ListView控件中item的布局popup_text_item.xml文件

<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="35sp"
android:gravity="center"/>