Android 反射的使用-通用各种数据类型的下拉选框PopupWindow

今天我们要用到的反射的知识是:根据属性名称获取属性对应的值。

如果觉得需要的话可以直接拿去用, 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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值