android 标题栏下拉选择控件(下拉菜单宽度全屏显示spinner)

android下拉菜单spinner,虽然很方便,但有些需求是下拉框是固定大小,下拉菜单栏则是宽度全屏,据我所知android自带的spinner是不好处理的,所以就自己动手吧,自己动手有饭吃。废话少说,先上图再说

android 标题栏下拉选择控件(下拉菜单宽度全屏显示spinner)_第1张图片

这里的实现方案是TextView加PopupWindow,并对其进行了封装。

照惯例,我们仍然从简单的说起,首先是适配器,因为我们的下拉列表其实就是一个listView,所以该适配器直接继承BaseAdapter,在这里我们只增加一个抽象方法getItemText(int position),用于TextView获取显示的文本,代码如下:

public abstract class BaseSpinnerAdapter extends BaseAdapter {

    public abstract String getItemText(int position);

}


这次的控件会比较简单,只是TextView和PopupWindow的组合控件,所以理所当然的该控件直接继承TextView,然后分一下几步

1、在构造方法中创建一个PopWindow,代码如下:

 /**
     * 初始化列表PopupWindow
     */
    public void init(Context context) {
        setGravity(Gravity.CENTER);
        LinearLayout layout = new LinearLayout(context);
        layout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT));
        layout.setBackgroundColor(0xaa000000);
        layout.setOrientation(LinearLayout.VERTICAL);
        mPopWindow = new PopupWindow(layout, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, true);
        mPopWindow.setAnimationStyle(animationId);

        line = new View(context);//添加一条分割线,不需要可将其设置为透明色
        float scale = context.getResources().getDisplayMetrics().density;
        line.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                (int) (1 * scale + 0.5f)));
        line.setBackgroundColor(lineColor);
        listView = new ListView(context);
        listView.setDivider(new ColorDrawable(0xffd6d6d6));
        listView.setDividerHeight(1);
        listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);//设置为单选模式,方便获取最新的点击item的下标
        if (adapter != null) {
            listView.setAdapter(adapter);
        }
        layout.addView(line);
        layout.addView(listView);


        layout.setFocusableInTouchMode(true);
        mPopWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {//向外部暴露popWindow消失时的通知接口
            @Override
            public void onDismiss() {
                if (statusListener != null) {
                    statusListener.onDismiss(PopSpinner.this);
                }
            }
        });
	//点击空白处时,关闭PopWindows
        layout.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                closeWindow();
                return false;
            }
        });
        layout.setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                closeWindow();
                return true;
            }
        });
        setOnClickListener(this);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                if (adapter != null) {
                    PopSpinner.this.setText(adapter.getItemText(position));
                }
                closeWindow();
                if (mOnSpinnerItemClickListener != null) {
                    mOnSpinnerItemClickListener.onItemClick(parent, view, position, id);
                }
            }
        });
    }


2、修改setOnClickListener方法,使点击该控件时弹出下拉菜单,再调用外部设置的点击事件,代码如下:


------------------------------------------------
@Override
    public void setOnClickListener(OnClickListener l) {
        if (l instanceof PopSpinner) {
            super.setOnClickListener(l);
        } else {
            this.onClickListener = l;
        }
    }

    @Override
    public void onClick(View view) {
        if (mPopWindow.isShowing()) {
            closeWindow();
        } else {
            showWindow();
        }
        if (onClickListener != null) {
            onClickListener.onClick(view);
        }
    }
------------------------------------------------

3、定义外部响应接口

------------------------------------------------
//下拉列表的item点击事件,即listView的item点击事件
 public interface OnSpinnerItemClickListener {
        void onItemClick(AdapterView parent, View view, int position, long id);
    }

    //下拉列表显示与隐藏事件
    public interface WindowStatusListener {
        //下拉列表显示
        void onShow(View view);

        // 下拉列表隐藏
        void onDismiss(View view);
    }
------------------------------------------------


4、丰富特色设置

----------------------------------------------
//设置adapter  
public void setAdapter(BaseSpinnerAdapter adapter) {
        this.adapter = adapter;
        if (listView != null) {
            listView.setAdapter(adapter);
        }
        if (adapter.getCount() > 0) {
            setSelectedItemPosition(0);
        }
    }
    //方便外部获取下拉列表的listView
    public ListView getListView() {
        return listView;
    }

   // 设置PopWindows显示隐藏动画
    public void setAnimationStyle(int animationId) {
        if (mPopWindow != null) {
            mPopWindow.setAnimationStyle(animationId);
        }
        this.animationId = animationId;
    }
    /**
     * 获取当前选中的item
     *
     * @return
     */
    public int getSelectedItemPosition() {
        if (listView != null) {
            return listView.getCheckedItemPosition();
        }
        return 0;
    }
   //获取选中的对象
    public Object getSelectItemObject() {
        if (adapter != null && adapter.getCount() > 0) {
            return adapter.getItem(getSelectedItemPosition());
        }
        return null;
    }
   //设置选中第几个
    public void setSelectedItemPosition(int position) {
        if (listView != null && listView.getCount() > 0) {
            listView.setItemChecked(listView.getCount() > position ? position : listView.getCount() - 1, true);
        }
        if (adapter != null && adapter.getCount() > 0) {
            setText(adapter.getItemText(adapter.getCount() > position ? position : adapter.getCount() - 1));
        }
    }
   //设置顶部分割线的颜色
    public void setLineColor(int lineColor) {
        if (line != null) {
            line.setBackgroundColor(lineColor);
        }
        this.lineColor = lineColor;
    }
------------------------------------------------


到此我们的下拉控件就完成了,使用上数据源和item的设置跟listView几乎差不多,控件中的样式的配置则跟TextView一样(因为本身就是继承TextView的),比如上图中的样式

------------------------------------------------
        popSpinner = new PopSpinner(this);
        ActionBar.LayoutParams lp = new ActionBar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
                , ViewGroup.LayoutParams.MATCH_PARENT);
        lp.gravity = Gravity.CENTER;
        popSpinner.setLayoutParams(lp);
        popSpinner.setTextSize(16);
        Drawable drawable = getResources().getDrawable(R.mipmap.arrow_down);
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        popSpinner.setCompoundDrawables(null, null, drawable, null);
        popSpinner.setCompoundDrawablePadding(15);
------------------------------------------------

至于下拉列表中打勾的显示方式,可以在你继承的adapter中做个标记位,选中的item显示个勾。实现方案有很多种,我这里又是使用自己定义的控件,思路是TextView+RadioButton,比较简单,我查了下,网上也有不少,这里就不讲了。


本文地址:http://blog.csdn.net/lanqi_x/article/details/78039435

你可能感兴趣的:(android)