近期公司项目中需要用到下拉框,为了省事于是就用了自带的Spinner,但使用后发现一个问题,就是不能设置提示文字。。并且,在父类是FragmentActivity的时候,还会有不一样的显示,总之使用起来非常的不爽。。于是就决定自己动手封装一个Spinner来实现自己的效果,其实实现起来也是比较的简单的,下面我们来一起看看吧。
首先来看看使用效果:
就是上图中的景区级别选框。
其实这个的主要思路就是一个TextView负责显示和监听用户的点击事件,还有一个PopupWindow负责显示内容和监听用户点击事件。
下面来看看详细代码吧:
首先是自定义一个PopupWindow:(代码很容易看懂,我就不写注释了)
/**
* 自定义PopupWindow
* Created by 05 on 2016/9/29.
*/
public class SpinnerPopWindow extends PopupWindow {
private LayoutInflater inflater;
private ListView mListView;
private List list;
private PopUpAdapter popAdapter;
public SpinnerPopWindow(Context context, List list,OnItemClickListener clickListener) {
super(context);
inflater = LayoutInflater.from(context);
this.list = list;
init(clickListener);
}
private void init(OnItemClickListener clickListener){
View view = inflater.inflate(R.layout.spiner_window_layout, null);
setContentView(view);
setWidth(LinearLayout.LayoutParams.WRAP_CONTENT);
setHeight(LinearLayout.LayoutParams.WRAP_CONTENT);
setFocusable(true);
ColorDrawable dw = new ColorDrawable(0x00);
setBackgroundDrawable(dw);
mListView = (ListView) view.findViewById(R.id.popup_listview);
mListView.setAdapter(popAdapter = new PopUpAdapter());
mListView.setOnItemClickListener(clickListener);
}
private class PopUpAdapter extends BaseAdapter{
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if(convertView == null){
viewHolder = new ViewHolder();
convertView = inflater.inflate(R.layout.pop_up_spinner_layout_item,null);
viewHolder.textTv = (TextView) convertView.findViewById(R.id.pop_up_item_text_tv);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.textTv.setText(getItem(position).toString());
return convertView;
}
}
private class ViewHolder{
private TextView textTv;
}
}
/**
* 自定义Spinner
* Created by 05 on 2016/9/29.
*/
public class CustomSpinner extends RelativeLayout {
private Context context;
private List textList;
private View customSpinnerView;
public TextView showTextTv;
private SpinnerPopWindow mpopWindow;
private String showTitle;
private String showText;
private OnCustomItemCheckedListener onCustomItemCheckedListener;
public CustomSpinner(Context context, String showTitle, List textList) {
super(context);
this.context = context;
this.showTitle = showTitle;
this.textList = textList;
init();
}
public interface OnCustomItemCheckedListener{
void OnCustomItemChecked(int position);
}
public void setOnCustomItemCheckedListener(OnCustomItemCheckedListener onCustomItemCheckedListener){
this.onCustomItemCheckedListener = onCustomItemCheckedListener;
}
private void init() {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
customSpinnerView = inflater.inflate(R.layout.custom_spinner_layout, this);
showTextTv = (TextView) customSpinnerView.findViewById(R.id.custom_msg_tv);
showTextTv.setText(showTitle);
showTextTv.setOnClickListener(clickListener);
mpopWindow = new SpinnerPopWindow<>(getContext(), textList, itemClickListener);
mpopWindow.setOnDismissListener(dismissListener);
}
//设置显示的提示文字
public String getShowText(){
return showText;
}
//对PopupWindow监听选中用户点击的项
public void setSelectionItem(int position){
showTextTv.setText(textList.get(position));
}
/**
* 监听popupwindow取消
*/
private PopupWindow.OnDismissListener dismissListener = new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
setTextImage(R.mipmap.spinner_up);
}
};
/**
* popupwindow显示的ListView的item点击事件
*/
private AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
mpopWindow.dismiss();
showTextTv.setText(textList.get(position));
showText = textList.get(position);
//这个接口是用来在其他界面做点击操作的时候负责调用的
if(onCustomItemCheckedListener!= null){
onCustomItemCheckedListener.OnCustomItemChecked(position);
}
}
};
/**
* 显示PopupWindow
*/
private View.OnClickListener clickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.custom_msg_tv:
mpopWindow.setWidth(showTextTv.getWidth());
mpopWindow.showAsDropDown(showTextTv);
setTextImage(R.mipmap.spinner_down);
break;
}
}
};
/**
* 给TextView右边设置图片
*
* @param resId
*/
private void setTextImage(int resId) {
Drawable drawable = getResources().getDrawable(resId);
drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());// 必须设置图片大小,否则不显示
showTextTv.setCompoundDrawables(null, null, drawable, null);
}
}
现在来看一下怎样使用这个自定义的Spinner。
scenicLevels = getResources().getStringArray(R.array.levels);
List levelList = Arrays.asList(scenicLevels);
levelSpinner = new CustomSpinner(getContext(), "请选择评分", levelList);
levelLl.addView(levelSpinner);
在实例化CustomSpinner之后记得用一个线性布局.addView方法将自定义的Spinner添加进去。
通过这些方法,一个自定义的Spinner就做好了,当然了,由于自己能力有限,可能还有一些小问题,使得这个Spinner不够优雅,但起码这也算是一种思路,你们也可以把我的这个方法做一个更好的优化,让它更加的优雅。。。哈哈哈,如果有什么问题的话,欢迎来和我一起交流,在码农的这条路上我们一起进步。~~