Android 自定义下拉列表

Android 下拉列表也是一个比较常用的控件,但是Android自带的下拉框样式效果较差,没办法,只好自己来自定义一个。其实主要是利用弹窗来实现的,看一下效果图先~~


我这边仅仅是实现简单的自定义控件,简单易懂,布局上有需要其他效果如边框、虚线等可自行加上。下拉列表是List,所以item也是可以根据需要进行内容上的丰富,修改适配器便可以。

好了,进入正题。首先,我们先创建一个标题及箭头布局,目的是用于点击后弹出下拉菜单。,代码如下所示:


   
   

    
    
    

        
     
     

        
     
     
    
    
    


   
   
接下来,创建下拉列表ListView布局,代码如下:

    
    

    
    

    
     
     
    
     
     


    
    
创建ListView,自然也要对应创建其Item的布局,代码如下:

    
    

    
    

    
     
     
    

    
    
接下来,我们来封装一个自定义控件MySpinerView,由于我没有去找向上箭头的图片资源,大家箭头自行替换。代码如下:
package com.newland.myspinerdemo;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.List;

/**
 * 封装好的下拉列表,包括头部
 */
public class MySpinerView extends LinearLayout implements View.OnClickListener, MySpinerAdapter.IOnItemSelectListener {
    private String mExampleString = "";
    private int mExampleColor = Color.RED;
    private float mExampleDimension = 0;

    private Context context;
    private RelativeLayout spiner;
    private TextView tvSpiner;
    private ImageView ivSpiner;
    private List
    
    
     
      nameList;

    private MySpinerPopWindow mSpinerPopWindow;

    public MySpinerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        LayoutInflater.from(context).inflate(R.layout.sample_my_spiner_view, this);
        init(attrs, 0);
        spiner = (RelativeLayout) this.findViewById(R.id.spiner);
        spiner.setOnClickListener(this);
        tvSpiner = (TextView) this.findViewById(R.id.tv_spiner);
        ivSpiner = (ImageView) this.findViewById(R.id.iv_spiner);
    }

    /**
     * 设置弹出下拉表单的数据,在Activity那边得到控件后记得调用否则抛异常
     * @param nameList
     */
    public void setData(List
     
     
      
       nameList) {
        this.nameList = nameList;
        mSpinerPopWindow = new MySpinerPopWindow(context);
        mSpinerPopWindow.refreshData(nameList, 0);
        mSpinerPopWindow.setItemListener(this); // 设置下拉列表item点击的监听,响应onItemClick回调函数
    }

    /**
     * 头部点击事件
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.spiner:
                showSpinWindow();
                break;
        }
    }

    /**
     * 弹出下拉列表
     */
    public void showSpinWindow() {
        /**这里还有一步要做,就是让右边箭头向上。自己替换掉ivSpiner图片**/
        mSpinerPopWindow.setWidth(((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth());
        mSpinerPopWindow.showAsDropDown(tvSpiner);
    }

    /**
     * 下拉列表项点击事件,把选中的值显示在界面上
     * @param pos
     */
    @Override
    public void onItemClick(int pos) {
        /**这里还有一步要做,就是让右边箭头还原向下。自己替换掉ivSpiner图片**/
        if (pos >= 0 && pos <= nameList.size()) { // pos为-1就是弹窗消失,不管他
            String value = nameList.get(pos);
            tvSpiner.setText(value);
        }
    }

    /**
     * 初始化顶部显示数据
     * @param txt
     */
    public void initText(String txt){
        tvSpiner.setText(txt);
    }
}

     
     
    
    
自定义控件创建完毕,点击后弹出的下拉列表。

下拉列表实际上是一个PopWindow,里面有一个ListView,所以我们新建一个自定义弹窗PopWindow。代码如下:
package com.newland.myspinerdemo;

import java.util.List;

import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.PopupWindow;

/**
 * 下拉列表弹窗
 */
public class MySpinerPopWindow extends PopupWindow implements OnItemClickListener {

    private Context mContext;
    private ListView mListView;
    private MySpinerAdapter mAdapter;
    private MySpinerAdapter.IOnItemSelectListener mItemSelectListener;


    public MySpinerPopWindow(Context context) {
        super(context);
        mContext = context;
        init();
    }

    /**
     * 为MySpinnerView提供一个item点击事件的监听器,MySpinnerView实例调用此方法设置监听
     * @param listener
     */
    public void setItemListener(MySpinerAdapter.IOnItemSelectListener listener) {
        mItemSelectListener = listener;
    }

    /**
     * 初始化弹窗布局
     */
    private void init() {
        View view = LayoutInflater.from(mContext).inflate(R.layout.spiner_window_layout, null);
        setContentView(view);
        setWidth(LayoutParams.WRAP_CONTENT);
        setHeight(LayoutParams.WRAP_CONTENT);

        setFocusable(true);
        ColorDrawable dw = new ColorDrawable(0x00);
        setBackgroundDrawable(dw);

        mListView = (ListView) view.findViewById(R.id.listview);

        mAdapter = new MySpinerAdapter(mContext);
        mListView.setAdapter(mAdapter);
        mListView.setOnItemClickListener(this);
        this.setOnDismissListener(new OnDismissListener() { // 弹窗消失的监听
            @Override
            public void onDismiss() {
                if (mItemSelectListener != null) {
                    mItemSelectListener.onItemClick(-1); // 弹窗消失,要让布局那边的箭头还原向下,所以那边还得判断一下,>=0的数据在显示,-1就忽略掉,箭头还原
                }
            }
        });
    }

    /**
     * 刷新下拉列表的数据
     * @param list
     * @param selIndex
     */
    public void refreshData(List
    
    
     
      list, int selIndex) {
        if (list != null && selIndex != -1) {
            mAdapter.refreshData(list, selIndex);
        }
    }

    /**
     * 下拉列表ListView的点击事件。
     * @param arg0
     * @param view
     * @param pos
     * @param arg3
     */
    @Override
    public void onItemClick(AdapterView
     
      arg0, View view, int pos, long arg3) {
        dismiss();
        if (mItemSelectListener != null) {
            mItemSelectListener.onItemClick(pos); //点击后调用此方法,则MySpinerView会监听到(因为mItemSelectListener是MySpinerView那边设置的监听器)
        }
    }
}

    
    
既然是ListView,那么马上想到的就是适配器,那么我们接下来设置弹窗里面的ListView适配器,代码如下:
package com.newland.myspinerdemo;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MySpinerAdapter
    
    
     
      extends BaseAdapter {

    private Context mContext;
    private List
     
     
      
       mObjects = new ArrayList
      
      
       
       ();

    private LayoutInflater mInflater;

    public MySpinerAdapter(Context context) {
        mContext = context;
        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    /**
     * 刷新数据
     * @param objects
     * @param selIndex
     */
    public void refreshData(List
       
       
        
         objects, int selIndex) {
        mObjects = objects;
        if (selIndex < 0) {
            selIndex = 0;
        }
        if (selIndex >= mObjects.size()) {
            selIndex = mObjects.size() - 1;
        }
    }


    @Override
    public int getCount() {
        return mObjects.size();
    }

    @Override
    public Object getItem(int pos) {
        return mObjects.get(pos).toString();
    }

    @Override
    public long getItemId(int pos) {
        return pos;
    }

    @Override
    public View getView(int pos, View convertView, ViewGroup arg2) {
        ViewHolder viewHolder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.spiner_item_layout, null);
            viewHolder = new ViewHolder();
            viewHolder.mTextView = (TextView) convertView.findViewById(R.id.textView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        String item = (String) getItem(pos);
        viewHolder.mTextView.setText(item);
        return convertView;
    }

    public static class ViewHolder {
        public TextView mTextView;
    }

    /**
     * 提供一个设置点击事件监听的接口回调
     */
    public interface IOnItemSelectListener {
        void onItemClick(int pos);
    }

}

       
       
      
      
     
     
    
    
好了,功能性的东西都完成了,来看看主页面布局

主页面布局由4个自定义控件(MySpinerView)组成,代码如下:

    
    

    
    


    
     
     

    
     
     

    
     
     

    
     
     


    
    
最后一步,编写Activity,代码如下
package com.newland.myspinerdemo;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity{

    /**
     * 四个下拉列表头部数据
     */
    private String name1 = "课程类型";
    private String name2 = "教练";
    private String name3 = "卡路里";
    private String name4 = "时间";
    /**
     * 四个下拉列表数据
     */
    private List
    
    
     
      nameList1 = new ArrayList
     
     
      
      ();
    private List
      
      
       
        nameList2 = new ArrayList
       
       
        
        ();
    private List
        
        
          nameList3 = new ArrayList 
         
           (); private List 
          
            nameList4 = new ArrayList 
           
             (); /** * 四个自定义下拉列表 */ private MySpinerView mySpinerView1; private MySpinerView mySpinerView2; private MySpinerView mySpinerView3; private MySpinerView mySpinerView4; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setupViews(); } /** * 初始化四个下拉列表 */ private void setupViews() { mySpinerView1 = (MySpinerView)findViewById(R.id.mysv1); mySpinerView1.initText(name1); String[] names1 = { "高级课程", "中级课程", "所有课程" }; for (int i = 0; i < names1.length; i++) { nameList1.add(names1[i]); } mySpinerView1.setData(nameList1); mySpinerView2 = (MySpinerView)findViewById(R.id.mysv2); mySpinerView2.initText(name2); String[] names2 = {"小鱼","布拉特", "杰克逊", "菲尔顿", "希伯特"}; for (int i = 0; i < names2.length; i++) { nameList2.add(names2[i]); } mySpinerView2.setData(nameList2); mySpinerView3 = (MySpinerView)findViewById(R.id.mysv3); mySpinerView3.initText(name3); String[] names3 = {"10.0","20.0", "30.0", "40.0", "50.0"}; for (int i = 0; i < names3.length; i++) { nameList3.add(names3[i]); } mySpinerView3.setData(nameList3); mySpinerView4 = (MySpinerView)findViewById(R.id.mysv4); mySpinerView4.initText(name4); String[] names4 = {"1min","1hour", "1day", "1year", "forever"}; for (int i = 0; i < names4.length; i++) { nameList4.add(names4[i]); } mySpinerView4.setData(nameList4); } } 
            
           
          
        
       
       
      
      
     
     
    
    

大功告成~~~


附上源码下载链接: Android 自定义下拉列表 源码

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值