今天我们要用到的反射的知识是:根据属性名称获取属性对应的值。
如果觉得需要的话可以直接拿去用, github地址:https://github.com/shouPol/MyDemo
做了两种数据类型的效果图:
通用数据类型的下拉选框PopupWindow的实现思路:
在adapter绑定数据的时候,通过反射获取到我们想显示的字段的值显示出来。
直接看一下代码(代码中有注释,相信你能看懂)
首先是baseAdapter的封装(里面都有注释,应该能看懂):
package cn.humanetplan.mydemo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* 自定义 Adapter 抽象 基类
* 2019/6/6
*/
public abstract class AdapterBase<T> extends BaseAdapter {
private Context context;
private ArrayList<T> list;
private int resId;
private List<View> viewList = new ArrayList<>();
public AdapterBase(Context context, int resId) {
this.context = context;
this.resId = resId;
this.list = new ArrayList<>();
}
/**
* 设置 单个数据
* 原有数据 将被清除
*
* @param t
*/
public void setData(T t) {
this.list.clear();
addData(t);
}
/**
* 设置 多个 数据
* 原有数据 将被清除
*
* @param list
*/
public void setDatas(List<T> list) {
this.list.clear();
addDatas(list);
}
/**
* 添加 单个 数据
* 原有数据不会 被清除
*
* @param t
*/
public void addData(T t) {
if (t == null) {
return;
}
if (this.list.contains(t)) {
return;
}
this.list.add(t);
notifyDataSetChanged();
}
/**
* 添加 多个 数据
* 原有 数据 不会被清除
*
* @param list
*/
public void addDatas(List<T> list) {
if (list == null) {
return;
}
this.list.addAll(list);
notifyDataSetChanged();
}
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
public ArrayList<T> getList() {
return list;
}
public void setList(ArrayList<T> list) {
this.list = list;
}
public int getResId() {
return resId;
}
public void setResId(int resId) {
this.resId = resId;
}
@Override
public int getCount() {
return list.size();
}
@Override
public T getItem(int position) {
if (position < list.size()) {
return list.get(position);
} else {
return null;
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(position+1 > viewList.size()){
convertView = LayoutInflater.from(context).inflate(resId, null);
viewList.add(convertView);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
} else {
convertView = viewList.get(position);
viewHolder = (ViewHolder) convertView.getTag();
}
bindDatas(viewHolder, list.get(position), position);
return convertView;
}
public abstract void bindDatas(ViewHolder viewHolder, T t, int position);
public class ViewHolder {
private HashMap<Integer, View> map;
private View viewGroup;
public ViewHolder(View viewGroup) {
this.viewGroup = viewGroup;
this.map = new HashMap<>();
}
public View getView(int viewId) {
if (map.containsKey(viewId)) {
return map.get(viewId);
} else {
View viewFind = this.viewGroup.findViewById(viewId);
map.put(viewId, viewFind);
return viewFind;
}
}
public View getViewGroup() {
return viewGroup;
}
public void setViewGroup(View viewGroup) {
this.viewGroup = viewGroup;
}
}
}
然后是下拉选择框的adpter:
package cn.humanetplan.mydemo;
import android.content.Context;
import android.graphics.Color;
import android.widget.TextView;
/**
* 2019/6/6.
*/
public abstract class AdapterBaseChoosed<T> extends AdapterBase<T> {
private int selectPosition = -1;
private String typeName;
private Context context;
//不带复选框
public AdapterBaseChoosed(Context context, String typeName, int layoutId) {
super(context, layoutId);
this.context = context;
this.typeName = typeName;
}
public int getSelectPosition() {
return selectPosition;
}
public void setSelectPosition(int selectPosition) {
this.selectPosition = selectPosition;
notifyDataSetChanged();
}
@Override
public void bindDatas(ViewHolder viewHolder, T t, final int position) {
TextView text = (TextView) viewHolder.getView(R.id.textViewName);
String name = Utils.getAttributeValue(t, typeName);
text.setText(name);
if (position == selectPosition) {
text.setTextColor(Color.WHITE);
viewHolder.getViewGroup().setBackgroundColor(context.getResources().getColor(R.color.green_light));
} else {
text.setTextColor(context.getResources().getColor(R.color.item_content_new));
viewHolder.getViewGroup().setBackgroundColor(context.getResources().getColor(R.color.white));
}
}
}
然后是popupwindow:
package cn.humanetplan.mydemo;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.PopupWindow;
import java.util.List;
public class PopwindowSingleChoose<T> extends PopupWindow implements View.OnClickListener {
private ListView lv_pums;
private Context context;
private int windowWidth = 0;
private int selectPos = 0;//选择的位置
String names = "";//选中的文本
private DataChoosedListner listner;//选择回调事假
//设置选择回调
public void setListner(DataChoosedListner listner) {
this.listner = listner;
}
private AdapterBaseChoosed mAdapter;//通用选择adapter
private String typeName; //要显示的内容在实体中对应的属性名称
private List<T> dataList;//下拉显示的数据源
//设置选择位置
public void setSelectPos(int selectPos) {
this.selectPos = selectPos;
if (mAdapter != null) {
mAdapter.setSelectPosition(selectPos);
}
}
//设置弹出宽度
public void setWindowWidth(int width) {
this.windowWidth = width;
this.setWidth(windowWidth);
}
//设置数据源
public void setDataList(List<T> dataList) {
this.dataList = dataList;
initAdapter();
}
public PopwindowSingleChoose(final Context context, int width, String typeName) {
this(context, null, width, typeName);
}
public PopwindowSingleChoose(final Context context, List<T> list, int width, String typeName) {
super(context);
this.context = context;
this.windowWidth = width;
this.typeName = typeName;
this.dataList = list;
final View view = View.inflate(context, R.layout.pop_sigle_choose, null);
lv_pums = (ListView) view.findViewById(R.id.lv_pums);
//设置SelectPicPopupWindow的View
this.setContentView(view);
//设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(width);
//设置SelectPicPopupWindow弹出窗体的高
this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
//设置SelectPicPopupWindow弹出窗体可点击
this.setFocusable(true);
// this.setOutsideTouchable(true);
//设置SelectPicPopupWindow弹出窗体动画效果
// this.setAnimationStyle(R.style.AnimBottom);
//实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0xb0000000);
//设置SelectPicPopupWindow弹出窗体的背景
this.setBackgroundDrawable(dw);
//此处是设置点击其他地方隐藏窗口
view.setOnTouchListener(new View.OnTouchListener() {
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View v, MotionEvent event) {
int height = view.findViewById(R.id.ll_content).getTop();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_UP) {
if (y < height) {
dismiss();
}
}
return true;
}
});
initAdapter();
}
/**
* 初始化数据
*/
private void initAdapter() {
if (dataList == null) {
return;
}
mAdapter = new AdapterBaseChoosed(context, typeName, R.layout.item_listview_single_text) {
};
mAdapter.setDatas(dataList);
names = Utils.getAttributeValue(dataList.get(selectPos), typeName);
lv_pums.setAdapter(mAdapter);
mAdapter.setSelectPosition(selectPos);
lv_pums.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
names = Utils.getAttributeValue(dataList.get(position), typeName);
selectPos = position;
mAdapter.setSelectPosition(selectPos);
if (listner != null) {
listner.onDataChoosed(names, selectPos);
dismiss();
}
}
});
}
@Override
public void onClick(View v) {
}
/**
* 回调接口
*
* @author Administrator
*/
public interface DataChoosedListner {
void onDataChoosed(String names, int pos);
}
}
Utils代码:
package cn.humanetplan.mydemo;
import android.text.TextUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* date : 2019/6/6.
*/
public class Utils {
//根据属性名称获取对应的值
public static <T> String getAttributeValue(T t, String typeName) {
String str = "";
if (t == null) {
return str;
}
if (typeName == null || TextUtils.isEmpty(typeName)) {
return str;
}
try {
Field field = t.getClass().getDeclaredField(typeName);
field.setAccessible(true);
str = (String) field.get(t);
return str;
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return str;
}
//根据属性名称设置该属性在实体中的值
public static <T> T setValueByFieldName(String typeName, T t, String val) {
String value = "";
try {
if (typeName == null) {
} else {
Class<?> clz = t.getClass();
Field field = clz.getDeclaredField(typeName);
field.setAccessible(true);
if (field.getGenericType().toString().equals("class java.lang.String")) {
Method method = t.getClass().getMethod("set" + getMethodName(field.getName()), String.class);
method.invoke(t, val);
}
if (field.getGenericType().toString().equals("class java.lang.Integer"))//
{
Method method = t.getClass().getMethod("set" + getMethodName(field.getName()), Integer.class);
method.invoke(t, Integer.parseInt(val));
}
}
} catch (Exception e) {
} finally {
return t;
}
}
/**
* 将属性名称的首字母变成大写
*/
public static String getMethodName(String fieldName) {
byte[] bytes = fieldName.getBytes();
bytes[0] = (byte) (bytes[0] - 'a' + 'A');
return new String(bytes);
}
}
再看一下MainActivity的实现:
package cn.humanetplan.mydemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import cn.humanetplan.mydemo.Bean.DataType;
import cn.humanetplan.mydemo.Bean.Person;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
TextView tv_type, tv_person;
private List<Person> personList=new ArrayList<>();//负责人数据
private List<DataType> typeList=new ArrayList<>();//类别数据
PopwindowSingleChoose personPop, typePop;//popupwindow
//选择负责人的回调
private PopwindowSingleChoose.DataChoosedListner personChooseListener = new PopwindowSingleChoose.DataChoosedListner() {
@Override
public void onDataChoosed(String names, int pos) {
tv_person.setText(names);
}
};
//选择类型的回调
private PopwindowSingleChoose.DataChoosedListner typeChooseListener = new PopwindowSingleChoose.DataChoosedListner() {
@Override
public void onDataChoosed(String names, int pos) {
tv_type.setText(names);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InitViews();
InitData();
InitListeners();
}
private void InitViews() {
tv_person = findViewById(R.id.tv_person);
tv_type = findViewById(R.id.tv_type);
}
private void InitListeners() {
tv_person.setOnClickListener(this);
tv_type.setOnClickListener(this);
}
private void InitData() {
for (int i=0;i<6;i++){
Person p=new Person((int)Math.random()*10+16,"人员"+(i+1));
personList.add(p);
DataType type=new DataType("类别"+(i+1),"type"+(i*10+1));
typeList.add(type);
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_person:
showPop("person");
break;
case R.id.tv_type:
showPop("type");
break;
}
}
private void showPop(String river) {
PopwindowSingleChoose pop = null;
switch (river) {
case "person":
if (personPop == null) {
personPop = new PopwindowSingleChoose(this, personList, tv_person.getWidth(), "name");
personPop.setListner(personChooseListener);
}
if (personPop.isShowing()) {
personPop.dismiss();
} else {
personPop.showAsDropDown(tv_person, 0, 0);
}
break;
case "type":
if (typePop == null) {
typePop = new PopwindowSingleChoose(this, typeList, tv_type.getWidth(), "typeName");
typePop.setListner(typeChooseListener);
}
if (typePop.isShowing()) {
typePop.dismiss();
} else {
typePop.showAsDropDown(tv_type, 0, 0);
}
break;
}
}
}
github地址:https://github.com/shouPol/MyDemo