zoukankan      html  css  js  c++  java
  • Android 自定义 SpinnerButton(转)

     

    Android 自定义 SpinnerButton

    模仿Android4.0的Spinner Button写的一个MySpinnerButton。这样在1.6~4.0.4版本都可以实现这种下拉框的效果了。

    实现效果:点击屏幕上的Spinner Button,在按钮的下方会滑出一个下拉列表,滑动选择下拉列表中其中一个选项,则下拉列表收回,按钮上的文字显示为选项的内容。点击返回键或下拉列表外部区域,下拉列表收回。反复点击按钮,下拉列表反复执行滑出和收回动作。

    运行图:

        

    实现原理:使用PopupWindow和Button相关联(showAsDropDown)。在PopupWindow上放ListView。于是就有了下拉框的效果。

    以下是代码:

    入口_04MySpinnerDemo2Activity:

    public class _04MySpinnerDemo2Activity extends Activity {

    private MySpinnerButton mSpinnerBtn;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    this.mSpinnerBtn = (MySpinnerButton) this.findViewById(R.id.spinner_btn);
    }
    }

    布局文件main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="top|center_horizontal"
    android:orientation="vertical" >

    <com.haozi.demo.myspinner2.wiget.MySpinnerButton
    android:id="@+id/spinner_btn"
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:text="spinner button"
    />

    </LinearLayout>

    封装好的MySpinnerButton:

    /**
    * 我的SpinnerButton
    * @author haozi
    *
    */
    public class MySpinnerButton extends Button {

    private Context context;

    public MySpinnerButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    // 设置监听事件
    setOnClickListener(new MySpinnerButtonOnClickListener());
    }

    public MySpinnerButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    // 设置监听事件
    setOnClickListener(new MySpinnerButtonOnClickListener());
    }

    public MySpinnerButton(Context context) {
    super(context);
    this.context = context;
    // 设置监听事件
    setOnClickListener(new MySpinnerButtonOnClickListener());
    }

    /**
    * MySpinnerButton的点击事件
    * @author haozi
    *
    */
    class MySpinnerButtonOnClickListener implements View.OnClickListener{

    @Override
    public void onClick(View v) {

    final MySpinnerDropDownItems mSpinnerDropDrownItems = new MySpinnerDropDownItems(context);
    if (!mSpinnerDropDrownItems.isShowing()) {
    mSpinnerDropDrownItems.showAsDropDown(MySpinnerButton.this);
    }
    }
    }

    /**
    * MySpinnerButton的下拉列表
    * @author haozi
    *
    */
    class MySpinnerDropDownItems extends PopupWindow{

    private Context context;
    private LinearLayout mLayout; // 下拉列表的布局
    private ListView mListView; // 下拉列表控件
    private ArrayList<HashMap<String, String>> mData;

    public MySpinnerDropDownItems(Context context){
    super(context);

    this.context = context;
    // 下拉列表的布局
    mLayout = new LinearLayout(context);
    mLayout.setOrientation(LinearLayout.VERTICAL);
    // 下拉列表控件
    mListView = new ListView(context);
    mListView.setLayoutParams(new LayoutParams(MySpinnerButton.this.getLayoutParams().width, LayoutParams.WRAP_CONTENT));
    mListView.setCacheColorHint(Color.TRANSPARENT);
    mData = new ArrayList<HashMap<String,String>>();
    for(int i=0; i<50; i++){
    HashMap<String, String> mHashmap = new HashMap<String, String>();
    mHashmap.put("spinner_dropdown_item_textview", "textView " + i);
    mData.add(mHashmap);
    }
    // 为listView设置适配器
    mListView.setAdapter(new MyAdapter(context,
    mData, R.layout.spinner_dropdown_item,
    new String[]{"spinner_dropdown_item_textview"}, new int[]{R.id.spinner_dropdown_item_textview}));
    // 设置listView的点击事件
    mListView.setOnItemClickListener(new MyListViewOnItemClickedListener());
    // 把下拉列表添加到layout中。
    mLayout.addView(mListView);

    setWidth(LayoutParams.WRAP_CONTENT);
    setHeight(LayoutParams.WRAP_CONTENT);
    setContentView(mLayout);
    setFocusable(true);

    mLayout.setFocusableInTouchMode(true);
    }

    /**
    * 我的适配器
    * @author haozi
    *
    */
    public class MyAdapter extends BaseAdapter {

    private Context context;
    private List<? extends Map<String, ?>> mData;
    private int mResource;
    private String[] mFrom;
    private int[] mTo;
    private LayoutInflater mLayoutInflater;

    /**
    * 我的适配器的构造方法
    * @param context 调用方的上下文
    * @param data 数据
    * @param resource
    * @param from
    * @param to
    */
    public MyAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to){

    this.context = context;
    this.mData = data;
    this.mResource = resource;
    this.mFrom = from;
    this.mTo = to;
    this.mLayoutInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
    }

    /**
    * 系统在绘制ListView之前,将会先调用getCount方法来获取Item的个数
    */
    public int getCount() {

    return this.mData.size();
    }

    public Object getItem(int position) {

    return this.mData.get(position);
    }

    public long getItemId(int position) {

    return position;
    }

    /**
    * 每绘制一个 Item就会调用一次getView方法,
    * 在此方法内就可以引用事先定义好的xml来确定显示的效果并返回一个View对象作为一个Item显示出来。
    * 也 正是在这个过程中完成了适配器的主要转换功能,把数据和资源以开发者想要的效果显示出来。
    * 也正是getView的重复调用,使得ListView的使用更 为简单和灵活。
    * 这两个方法是自定ListView显示效果中最为重要的,同时只要重写好了就两个方法,ListView就能完全按开发者的要求显示。
    * 而 getItem和getItemId方法将会在调用ListView的响应方法的时候被调用到。
    * 所以要保证ListView的各个方法有效的话,这两个方法也得重写。
    */
    public View getView(int position, View contentView, ViewGroup parent) {

    contentView = this.mLayoutInflater.inflate(this.mResource, parent, false);

    // 设置contentView的内容和样式,这里重点是设置contentView中文字的大小
    for(int index=0; index<this.mTo.length; index++){
    TextView textView = (TextView) contentView.findViewById(this.mTo[index]);
    textView.setText(this.mData.get(position).get(this.mFrom[index]).toString());
    }

    return contentView;
    }
    }

    /**
    * listView的点击事件
    * @author haozi
    *
    */
    class MyListViewOnItemClickedListener implements AdapterView.OnItemClickListener{

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {

    TextView mTextView = (TextView) view.findViewById(R.id.spinner_dropdown_item_textview);
    String content = mTextView.getText().toString();
    MySpinnerButton.this.setText(content);
    MySpinnerDropDownItems.this.dismiss();
    }
    }
    }
    }

    下拉列表item的布局文件spinner_dropdown_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:drawable/list_selector_background"
    android:orientation="vertical" >

    <TextView android:id="@+id/spinner_dropdown_item_textview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="left|bottom"
    android:paddingTop="11dip"
    android:paddingBottom="11dip"
    android:paddingLeft="5dip"
    />
    </LinearLayout>

  • 相关阅读:
    设计模式-策略模式
    .NET操作RabbitMQ组件EasyNetQ使用中文简版文档。
    LayIM项目之基础数据获取代码优化,Dapper取代ADO.NET
    干货!手把手教你如何使用第三方通讯服务实现LayIM Socket组件开发。
    几句代码简单实现IoC容器
    .NET Core On Mac 第一步,配置环境
    Func<T,T>应用之Elasticsearch查询语句构造器的开发
    四个人17分钟过桥的问题
    ElasticSearch中的简单查询
    ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(十四)之漏掉的客服消息
  • 原文地址:https://www.cnblogs.com/qingchen1984/p/3980248.html
Copyright © 2011-2022 走看看