〇、前言
PopupWindow在Android中是一个常用且极具生命力的控件,在好多地方都能看见,而且这几年Android技术一直更新迭代也没有PopupWindow的替代品出现。PopupWindow类似于Dialog,但是使用起来比Dialog则更加灵活,今天有空将自己在项目中的自定义PopupWindow做一个记录,实现起来其实挺简单的,但是细节还是不少。
一、自定义PopupWindow
package com.mliuxb.popupdemo;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* Description: MyPopupWindow
* Copyright : Copyright (c) 2021
* Author : mliuxb
* Date : 2021-05-01 21:17:06
*/
public final class MyPopupWindow extends PopupWindow {
private static final String TAG = "MyPopupWindow";
private final TextView mTextView;//用于PopupWindow定位的TextView
public MyPopupWindow(@NonNull Context context, @NonNull TextView textView) {
super(context);
this.mTextView = textView;
setContentView(context);
setWidth(textView.getWidth());
setHeight(dip2px(context, 200));
setFocusable(true);
setBackgroundDrawable(new ColorDrawable());
}
public void setContentView(@NonNull Context context) {
final RecyclerView recyclerView = new RecyclerView(context);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
final DividerItemDecoration itemDecoration = new DividerItemDecoration(context, DividerItemDecoration.VERTICAL);
itemDecoration.setDrawable(context.getResources().getDrawable(R.drawable.shape_recycler_list_divider_orange));
recyclerView.addItemDecoration(itemDecoration);
recyclerView.setAdapter(new PopupAdapter());
recyclerView.setBackgroundResource(R.drawable.shape_orange_rectangle_stroke_base);
setContentView(recyclerView);
}
private class PopupAdapter extends RecyclerView.Adapter<PopupHolder> {
@NonNull
@Override
public PopupHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
final Context context = parent.getContext();//context是当前Activity的对象
final int dip10 = dip2px(context, 10);
//final int dip15 = dip2px(context, 15);
final TextView textView = new TextView(context);
textView.setWidth(mTextView.getWidth());
textView.setTextSize(18);
//textView.setTextColor(context.getResources().getColor(R.color.blue_base));
textView.setTextColor(context.getResources().getColorStateList(R.color.selector_text_blue_orange));
textView.setPadding(dip10, dip10, dip10, dip10);
//textView.setBackgroundResource(R.drawable.selector_recycler_item_gray_sky);
return new PopupHolder(textView);
}
@Override
public void onBindViewHolder(@NonNull final PopupHolder holder, int position) {
final String[] selectItem = selectArr[position];
holder.textView.setTag(R.id.UID, selectItem[0]);
holder.textView.setTag(R.id.UTYPE, selectItem[1]);
holder.textView.setText(selectItem[2]);
holder.textView.setOnClickListener(v -> {
mTextView.setTag(R.id.UID, holder.textView.getTag(R.id.UID));
mTextView.setTag(R.id.UTYPE, holder.textView.getTag(R.id.UTYPE));
mTextView.setText(holder.textView.getText());
if (isShowing()) {
dismiss();
}
});
}
@Override
public int getItemCount() {
return selectArr.length;
}
}
private static class PopupHolder extends RecyclerView.ViewHolder {
private final TextView textView;
private PopupHolder(@NonNull TextView textView) {
super(textView);
this.textView = textView;
}
}
// 将dip或dp值转换为px值
private int dip2px(Context context, double dipValue) {
final double scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
//数组静态初始化:给出初始化值,由系统决定长度
private final String[][] selectArr = {
{"3", "LEADER", "张三"},
{"4", "WORKER", "李四"},
{"5", "WORKER", "王五"},
{"6", "WORKER", "周六"},
{"7", "WORKER", "赵七"},
{"8", "WORKER", "刘八"}
};
}
说明:
- 首先一般情况下我们都是针对一个TextView控件选择数据,所以在构造方法中将这个TextView传递进来,这样做有两个好处:其一是方便将PopupWindow的宽度设置为该TextView的宽度,其二是方便将选择的数据之间绑定到该TextView上,不用多余再声明其他变量,方便业务处理;
- 其次PopupWindow中使用了RecyclerView,RecyclerView的条目是TextView,这些控件都是new出来的,并没有使用布局文件以及布局填充器,这样自定义的PopupWindow消耗资源更少;
- 最后选择的数据是直接使用View.setTag()方法绑定在原TextView上的,数据传递极其方便。
三、使用
private PopupWindow mPopupWindow;
public void onClick(View view) {
final int viewId = view.getId();
if (viewId == R.id.tv_select_user) {
if (mPopupWindow == null) { //用户可能多次点击,不必重复创建对象
mPopupWindow = new MyPopupWindow(MainActivity.this, (TextView) view);
}
mPopupWindow.showAsDropDown(view);//显示PopupWindow小弹窗
}
}
使用也是非常的方便。