Android之——自定义下拉菜单的实现

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/48101651

做过Android开发的童鞋,一般都会遇到这样一种情况,就是Android中原有的下拉控件Spinner过于单调和简单,不能够满足我们实际开发的需求了,这时候就需要我们自己自定义下拉菜单来实现相应的功能,那么,如何实现自定义下拉菜单呢?下面我就来和大家一起实现这个功能。

一、原理

我们这个下拉菜单展示的内容主要以ListView实现,在界面上放置一个文本框,文本框右侧放置一个向下的箭头图标,表示可以点击下拉。然后创建一个item.xml布局文件,这个布局文件展示的就是ListView的条目信息,条目中有一个图片,表示头像,一串数字表示qq号(暂时以显示qq号为例),后面一个删除按钮。所有的数据封装在ListView中。然后我们将这个ListView以PopupWindow的形式显示在文本框的下面。

当ListView不显示的时候,点击文本框右侧的下拉图标,则弹出PopupWindow显示ListView

当ListView显示的时候,点击文本框右侧的下拉图标,则隐藏PopupWindow从而隐藏ListView

点击ListView中每一个条目后删除图标的时候,相应的条目就会从listView中消失。

二、实现

1、MainActivity

程序很简单,我将所有的java代码都写在了MainActivity中,我们还是分解来看这个类。

1)属性字段

每个字段代表的含义见代码注释

具体代码实现如下:

//界面控件
private ImageButton spinner;
private EditText et_name;
//构造qq号用到的集合
private List<String> names = new ArrayList<String>();
//布局加载器
private LayoutInflater mInflater;
//自定义适配器
private MyAdapter mAdapter;
//PopupWindow
private PopupWindow pop;
//是否显示PopupWindow,默认不显示
private boolean isPopShow = false;
2)自定义Adapter

同样,为了在ListView中更好的显示数据,我们还是用到了自定义Adapter

具体代码实现如下:

/**
 * 自定义Adapter
 * @author liuyazhuang
 *
 */
private class MyAdapter extends BaseAdapter{

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return names.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return names.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		View view = mInflater.inflate(R.layout.item, null);
		final TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
		tv_name.setText(names.get(position));
		ImageButton delete = (ImageButton) view.findViewById(R.id.delete);
		//设置按钮的监听事件
		delete.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				names.remove(position);
				isPopShow = true;
				mAdapter.notifyDataSetChanged();
			}
		});
		//设置按钮的监听事件
		tv_name.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				et_name.setText(names.get(position));
				pop.dismiss();
			}
		});
		return view;
	}

} 
3)onCreate方法

这个方法中主要实现的功能就是,初始化界面布局,为属性字段赋值,构造要在ListView中显示的数据,同时为相应的按钮设置点击事件,控制PopupWindow的显示和隐藏。

具体实现代码如下:

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	//构造qq账号
	for(int i = 10000; i < 10030; i++){
		names.add(String.valueOf(i));
	}
	spinner = (ImageButton) findViewById(R.id.spinner);
	et_name = (EditText) findViewById(R.id.et_name);
	mInflater = LayoutInflater.from(MainActivity.this);
	mAdapter = new MyAdapter();
	spinner.setOnClickListener(new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			// TODO Auto-generated method stub
			if(pop == null){
				ListView listView = new ListView(MainActivity.this);
				listView.setCacheColorHint(0x00000000);
				listView.setAdapter(mAdapter);
				pop = new PopupWindow(listView, et_name.getWidth(), LayoutParams.WRAP_CONTENT, true);
				pop.setBackgroundDrawable(new ColorDrawable(0x00000000));
				isPopShow = true;
			}
			if(isPopShow){
				pop.showAsDropDown(et_name, 0, 0);
				isPopShow = false;
			}else{
				pop.dismiss();
				isPopShow = true;
			}
		}
	});
}
4)完整代码如下:
package com.lyz.spiner.activity;

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

import android.os.Bundle;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

/**
 * 程序主入口
 * @author liuyazhuang
 *
 */
public class MainActivity extends Activity {
	//界面控件
	private ImageButton spinner;
	private EditText et_name;
	//构造qq号用到的集合
	private List<String> names = new ArrayList<String>();
	//布局加载器
	private LayoutInflater mInflater;
	//自定义适配器
	private MyAdapter mAdapter;
	//PopupWindow
	private PopupWindow pop;
	//是否显示PopupWindow,默认不显示
	private boolean isPopShow = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//构造qq账号
		for(int i = 10000; i < 10030; i++){
			names.add(String.valueOf(i));
		}
		spinner = (ImageButton) findViewById(R.id.spinner);
		et_name = (EditText) findViewById(R.id.et_name);
		mInflater = LayoutInflater.from(MainActivity.this);
		mAdapter = new MyAdapter();
		spinner.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if(pop == null){
					ListView listView = new ListView(MainActivity.this);
					listView.setCacheColorHint(0x00000000);
					listView.setAdapter(mAdapter);
					pop = new PopupWindow(listView, et_name.getWidth(), LayoutParams.WRAP_CONTENT, true);
					pop.setBackgroundDrawable(new ColorDrawable(0x00000000));
					isPopShow = true;
				}
				if(isPopShow){
					pop.showAsDropDown(et_name, 0, 0);
					isPopShow = false;
				}else{
					pop.dismiss();
					isPopShow = true;
				}
			}
		});
	}

	/**
	 * 自定义Adapter
	 * @author liuyazhuang
	 *
	 */
	private class MyAdapter extends BaseAdapter{

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return names.size();
		}

		@Override
		public Object getItem(int position) {
			// TODO Auto-generated method stub
			return names.get(position);
		}

		@Override
		public long getItemId(int position) {
			// TODO Auto-generated method stub
			return position;
		}

		@Override
		public View getView(final int position, View convertView, ViewGroup parent) {
			View view = mInflater.inflate(R.layout.item, null);
			final TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
			tv_name.setText(names.get(position));
			ImageButton delete = (ImageButton) view.findViewById(R.id.delete);
			//设置按钮的监听事件
			delete.setOnClickListener(new View.OnClickListener() {

				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					names.remove(position);
					isPopShow = true;
					mAdapter.notifyDataSetChanged();
				}
			});
			//设置按钮的监听事件
			tv_name.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					// TODO Auto-generated method stub
					et_name.setText(names.get(position));
					pop.dismiss();
				}
			});
			return view;
		}

	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

2、主布局文件activity_main.xml

具体实现代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black">

    <EditText
        android:id="@+id/et_name"
        android:layout_width="200dip"
        android:layout_height="wrap_content"
		android:layout_centerHorizontal="true"
		android:hint="请输入账号" />

	<ImageButton
	    android:id="@+id/spinner"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:background="@drawable/button"
	    android:layout_alignTop="@id/et_name"
	    android:layout_alignRight="@id/et_name"
	    android:layout_alignBottom="@id/et_name"/>
</RelativeLayout>

3、条目布局文件item.xml

具体实现代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center_vertical">
    <ImageView
        android:id="@+id/header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/user"/>

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>

    <ImageButton
        android:id="@+id/delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/delete"/>

</LinearLayout>

4、AndroidManifest.xml

最后贴出AndroidManifest.xml的代码

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lyz.spiner.activity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.lyz.spiner.activity.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

三、运行效果

四、温馨提示

大家可以到链接http://download.csdn.net/detail/l1028386804/9062795下载Android自定义下拉菜单示例完整源代码

本实例中,为了方面,我把一些文字直接写在了布局文件中和相关的类中,大家在真实的项目中要把这些文字写在string.xml文件中,在外部引用这些资源,切记,这是作为一个Android程序员最基本的开发常识和规范,我在这里只是为了方便直接写在了类和布局文件中。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-15 12:50:43

Android之——自定义下拉菜单的实现的相关文章

Android中自定义下拉样式Spinner

Android中自定义下拉样式Spinner 本文继续介绍android自定义控件系列,自定义Spinner控件的使用. 实现思路 1.定义下拉控件布局(ListView及子控件布局) 2.自定义SpinerPopWindow类 3.定义填充数据的Adapter 效果图 一.定义控件布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http:/

Android UI- PullToRrefresh自定义下拉刷新动画

Android UI- PullToRrefresh自定义下拉刷新动画 如果觉得本文不错,麻烦投一票,2014年博客之星投票地址:http://vote.blog.csdn.net/blogstar2014/details?username=wwj_748#content 本篇博文要给大家分享的是如何使用修改开源项目PullToRrefresh下拉刷新的动画,来满足我们开发当中特定的需求,我们比较常见的一种下拉刷新样式可能是以下这种: 就是下拉列表的时候两个箭头上下翻转,更改日期文本和刷新状态,

android中自定义下拉框(转)

android自带的下拉框好用不?我觉得有时候好用,有时候难有,项目规定这样的效果,自带的控件实现不了,那么只有我们自己来老老实实滴写一个新的了,其实最基本的下拉框就像一些资料填写时,点击的时候出现在编辑框的下面,然后又很多选项的下拉框,可是我在网上找了一下,没有这种下拉框额,就自己写了一个,看效果图先: ,这个是资料填写的一部分界面,三个下拉框,选择故乡所在地: 点击之后弹出下拉框,选择下面的选项: 三个下拉框时关联的,第一个决定了第二数据内容,第二个决定了第三个数据内容,如果三个全部选好之后

JS自定义下拉菜单select

由于系统自定的select样式的确丑到爆,所以抽空写了这么一个可以自定义下拉菜单样式的插件, 思路就是隐藏select,用一个span标签显示内容,ul标签显示下拉列表,如图: IE下存在一个BUG,设置overflow-y后,IE下设置width无效,只测试了IE9,其他版本未测试,当然如果能加入自定义样式的滚动条就完美了,时间关系以后再补吧 代码如下: 1 //自定义dropdownlist的样式, 2 //classname为模拟出来的span标签样式 3 //ulClass为下拉列表样式

iOS 下拉菜单 FFDropDownMenu自定义下拉菜单样式实战-b

Demo地址:https://github.com/chenfanfang/CollectionsOfExampleFFDropDownMenu框架地址:https://github.com/chenfanfang/FFDropDownMenu 老样子,先附上两张效果图 customMenuStyle.gif customMenuStyle.png 首先自定义一个继承于FFDropDownMenuBasedModel的菜单模型.h文件 #import <FFDropDownMenuBasedMo

Android PullToRrefresh 自定义下拉刷新动画 (listview、scrollview等)

PullToRefreshScrollView 自定义下拉刷新动画,只需改一处. 以下部分转载自http://blog.csdn.net/superjunjin/article/details/45022595 一,定义刷新动画的layout 在library下的com.handmark.pulltorefresh.library.internal包中的FlipLoadingLayout和RotateLoadingLayout FlipLoadingLayout为ios风格的箭头颠倒的刷新动画

css自定义下拉菜单,通过伪类控制展开隐藏

公司最近要做组件库,一些单选框,复选框,下拉菜单都需要美观自定义, 闲余时间做了一个(对浏览器要求较高的)下拉菜单的组件. /*********实现功能 start **************/ 通过css伪类:focus实现下拉菜单基本功能 select: 点击菜单(动画过渡)展开,再次点击(动画过渡)收起; 并保证点击页面空白处和选择option同样(动画过渡)收起菜单. option: 限制5条内容的高度,超出则滚动条,反之则自适应高度; /***********实现功能end*****

简易自定义下拉菜单 与简易默认下拉html片段

简易自定义下拉选择 html片段 html: <div class="select_box province"> <div class="selected">T时代C5</div> <div class="select_list_box" style="display:none;"> <div class="select_list">T时代C5&l

Android PullToRefreshView自定义下拉刷新控件

MyPullToRefreshView继承自LinearLayout,布局为vertical,该容器中包含三个子view,这三个view从上到下依次排列在LinearLayout中. 效果图如下: 下图中蓝色部分是充满屏幕的,HeaderView在ListView的上方,在代码中动态添加进来,使其底部Y轴坐标刚好为0,FooterView在ListView的下方,也在代码中动态添加进来,该View的TopMargin刚好为整个布局的高度. 首先看一下该控件的使用: 1.在xml中配置 <span