宁可枝头抱香死,何曾吹落北风中。这篇文章主要讲述Android 使用PopupWindow实现弹出更多的菜单相关的知识,希望能为你提供帮助。
最近想要做一个弹出更多的菜单,
而原生的弹出菜单却不是我们想要的效果,
所以必然要自定义菜单咯。本人也是借鉴网上的资料进行封装的,
感觉还蛮不错的。
原生的菜单如下图:
文章图片
自定义之后的效果图:
文章图片
文章图片
文章图片
是不是看到这里之后, 对比可知, 原生的效果不太理想, 所以还是再自己定义吧!
源码下载
1、PopupWindow可以说是一个浮动在Activity之上的容器, 通常用来显示自定义的视图。弹出菜单的封装PopMenuMore
/**
* 对弹出菜单的封装.
* http://blog.csdn.net/maosidiaoxian/article/details/39178167
* Author: msdx (645079761@
qq.com)
* Time: 14-6-13 下午1:51
*/
public class PopMenuMore {
/**
* 上下文.
*/
private Context mContext;
/**
* 菜单项
*/
private ArrayList<
PopMenuMoreItem>
mItemList;
/**
* 列表适配器.
*/
private BaseAdapter mAdapter;
/**
* 菜单选择监听.
*/
private OnItemSelectedListener mListener;
/**
* 下角图标
*/
private ImageView cornerIcon;
/**
* 列表.
*/
private ListView mListView;
/**
* 弹出窗口.
*/
private PopupWindow mPopupWindow;
public PopMenuMore(Context context) {
mContext =
context;
mItemList =
new ArrayList<
>
();
View view =
onCreateView(context);
view.setFocusableInTouchMode(true);
mAdapter =
onCreateAdapter(context, mItemList);
cornerIcon =
findCornerView(view);
mListView =
findListView(view);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@
Override
public void onItemClick(AdapterView<
?>
parent, View view, int position, long id) {
PopMenuMoreItem item =
(PopMenuMoreItem) mAdapter.getItem(position);
if (mListener !=
null) {
mListener.selected(view, item, position);
}
mPopupWindow.dismiss();
}
});
view.setOnKeyListener(new View.OnKeyListener() {
@
Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode =
=
KeyEvent.KEYCODE_MENU &
&
mPopupWindow.isShowing()) {
mPopupWindow.dismiss();
return true;
}
return false;
}
});
mPopupWindow =
new PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);
mPopupWindow.setBackgroundDrawable(new ColorDrawable(0x00000000));
setBackgroundColor(Color.parseColor("
#000000"
));
setCorner(R.mipmap.triangle);
}/**
* 设置ListView背景
*
* @
param argb Color.parseColor("
.."
)
*/
public void setBackgroundColor(int argb) {
//int strokeWidth =
5;
// 3dp 边框宽度
int roundRadius =
5;
// 8dp 圆角半径
//int strokeColor =
Color.parseColor("
#2E3135"
);
//边框颜色
//int fillColor =
Color.parseColor("
#DFDFE0"
);
//内部填充颜色
GradientDrawable gd =
new GradientDrawable();
//创建drawable
gd.setColor(argb);
gd.setCornerRadius(roundRadius);
//gd.setStroke(strokeWidth, strokeColor);
mListView.setBackgroundDrawable(gd);
}/**
* 设置下角图标
*
* @
param resId
*/
public void setCorner(int resId) {
cornerIcon.setBackgroundResource(resId);
}protected View onCreateView(Context context) {
return LayoutInflater.from(context).inflate(R.layout.layout_popmenu_more, null);
}protected ImageView findCornerView(View view) {
return (ImageView) view.findViewById(R.id.corner_iv);
}protected ListView findListView(View view) {
return (ListView) view.findViewById(R.id.menu_listview);
}/**
* 菜单列表中的适配器.
*
* @
param context
* @
param items表示所有菜单项.
* @
return
*/
protected BaseAdapter onCreateAdapter(Context context, ArrayList<
PopMenuMoreItem>
items) {
return new PopMenuMoreAdapter(context, items);
}/**
* 添加菜单项
*
* @
param item
*/
public void addItem(PopMenuMoreItem item) {
mItemList.add(item);
mAdapter.notifyDataSetChanged();
}public void addItems(List<
PopMenuMoreItem>
items) {
if (items !=
null) {
mItemList.clear();
}
for (PopMenuMoreItem item : items) {
mItemList.add(item);
}
mAdapter.notifyDataSetChanged();
}/**
* 作为指定View的下拉控制显示.
*
* @
param parent 所指定的View
*/
public void showAsDropDown(View parent) {
mPopupWindow.showAsDropDown(parent);
}/**
* 隐藏菜单.
*/
public void dismiss() {
mPopupWindow.dismiss();
}/**
* 设置菜单选择监听.
*
* @
param listener 监听器.
*/
public void setOnItemSelectedListener(OnItemSelectedListener listener) {
mListener =
listener;
}/**
* 当前菜单是否正在显示.
*
* @
return
*/
public boolean isShowing() {
return mPopupWindow.isShowing();
}/**
* 菜单项选择监听接口.
*/
public interface OnItemSelectedListener {
/**
* 菜单被选择时的回调接口.
*
* @
param view被选择的内容的View.
* @
param item被选择的菜单项.
* @
param position 被选择的位置.
*/
void selected(View view, PopMenuMoreItem item, int position);
}
}
2、菜单中ListView的适配器: PopMenuMoreAdapter
/**
* @
author SoBan
* @
create 2017/4/12 10:29.
*/public class PopMenuMoreAdapter extends BaseAdapter {private ArrayList<
PopMenuMoreItem>
items;
private Context context;
public PopMenuMoreAdapter(Context context, ArrayList<
PopMenuMoreItem>
items) {
this.context =
context;
this.items =
items;
}@
Override
public int getCount() {
return items.size();
}@
Override
public PopMenuMoreItem getItem(int position) {
return items.get(position);
}@
Override
public long getItemId(int position) {
return position;
}@
Override
public View getView(int position, View view, ViewGroup parent) {
if (view =
=
null) {
view =
LayoutInflater.from(context).inflate(R.layout.item_popmenu_more, null);
ViewHolder holder =
new ViewHolder();
holder.icon =
(ImageView) view.findViewById(R.id.menu_icon);
holder.text =
(TextView) view.findViewById(R.id.menu_text);
view.setTag(holder);
} else if (view.getParent() !=
null) {
((ViewGroup) view.getParent()).removeView(view);
}
ViewHolder holder =
(ViewHolder) view.getTag();
PopMenuMoreItem item =
items.get(position);
if (item.getResId() =
=
0) {
holder.icon.setVisibility(View.GONE);
}
holder.text.setText(item.getText());
return view;
}private class ViewHolder {
ImageView icon;
TextView text;
}
}
4、菜单项中item:PopMenuMoreItem
/**
* 菜单项.
*/
public class PopMenuMoreItem {
public int id;
//标识
public int resId;
//资源图标
public String text;
//文字public PopMenuMoreItem(int id, String text) {
this.id =
id;
this.resId =
0;
this.text =
text;
}public PopMenuMoreItem(int id, int resId, String text) {
this.id =
id;
this.resId =
resId;
this.text =
text;
}public int getId() {
return id;
}public void setId(int id) {
this.id =
id;
}public int getResId() {
return resId;
}public void setResId(int resId) {
this.resId =
resId;
}public String getText() {
return text;
}public void setText(String text) {
this.text =
text;
}
}
4、宽度适配内容、不滚动的ListView: PopMenuMoreListView
/**
* 宽度适配内容的ListView.
* Author: msdx (645079761@
qq.com)
* Time: 14-9-2 下午5:14
*/
public class PopMenuMoreListView extends ListView {public PopMenuMoreListView(Context context) {
super(context);
}public PopMenuMoreListView(Context context, AttributeSet attrs) {
super(context, attrs);
}public PopMenuMoreListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}@
Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width =
0;
for (int i =
0;
i <
getChildCount();
i+
+
) {
View child =
getChildAt(i);
child.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), heightMeasureSpec);
int w =
child.getMeasuredWidth();
if (w >
width) width =
w;
}widthMeasureSpec =
MeasureSpec.makeMeasureSpec(width +
getPaddingLeft() +
getPaddingRight(), MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
5、item的布局: item_popmenu_more.xml
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
LinearLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:paddingBottom=
"
10dip"
android:paddingLeft=
"
20dip"
android:paddingRight=
"
20dip"
android:paddingTop=
"
10dip"
>
<
ImageView
android:id=
"
@
+
id/menu_icon"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_gravity=
"
center_vertical"
android:layout_marginLeft=
"
5dip"
android:layout_marginRight=
"
5dip"
android:src=
"
@
mipmap/demand_icon_location"
/>
<
TextView
android:id=
"
@
+
id/menu_text"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_gravity=
"
center_vertical"
android:singleLine=
"
true"
android:textColor=
"
#FFFFFF"
/>
<
/LinearLayout>
6、更多菜单的布局: layout_popmenu_more.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=
"
wrap_content"
android:orientation=
"
vertical"
android:paddingRight=
"
5dip"
>
<
ImageView
android:id=
"
@
+
id/corner_iv"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_gravity=
"
right"
android:layout_marginRight=
"
15dip"
android:contentDescription=
"
@
null"
/>
<
soban.orderscroll.PopMenuMoreListView
android:id=
"
@
+
id/menu_listview"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:layout_gravity=
"
right"
android:cacheColorHint=
"
@
android:color/transparent"
android:listSelector=
"
@
android:color/transparent"
android:divider=
"
#FFFFFF"
android:dividerHeight=
"
1px"
android:focusable=
"
true"
/>
<
/LinearLayout>
7、例子Activity: MainActivity
public class MainActivity extends Activity {private static final int USER_SEARCH =
0;
private static final int USER_ADD =
1;
private PopMenuMore mMenu;
private TextView mTextView;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initMenu();
mTextView =
(TextView) findViewById(R.id.hello_tv);
mTextView.setOnClickListener(new View.OnClickListener() {
@
Override
public void onClick(View view) {
mMenu.showAsDropDown(mTextView);
}
});
}private void initMenu() {
mMenu =
new PopMenuMore(this);
// mMenu.setCorner(R.mipmap.demand_icon_location);
// mMenu.setBackgroundColor(Color.parseColor("
#ff8800"
));
ArrayList<
PopMenuMoreItem>
items =
new ArrayList<
>
();
items.add(new PopMenuMoreItem(USER_SEARCH, "
搜索"
));
items.add(new PopMenuMoreItem(USER_ADD, "
添加"
));
items.add(new PopMenuMoreItem(USER_SEARCH, "
搜索"
));
items.add(new PopMenuMoreItem(USER_ADD, "
添加"
));
items.add(new PopMenuMoreItem(USER_SEARCH, "
搜索"
));
items.add(new PopMenuMoreItem(USER_ADD, "
添加"
));
/*items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "
搜索"
));
items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "
添加"
));
items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "
搜索"
));
items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "
添加"
));
items.add(new PopMenuMoreItem(USER_SEARCH, R.mipmap.demand_icon_number, "
搜索"
));
items.add(new PopMenuMoreItem(USER_ADD, R.mipmap.demand_icon_location, "
添加"
));
*/mMenu.addItems(items);
mMenu.setOnItemSelectedListener(new PopMenuMore.OnItemSelectedListener() {
@
Override
public void selected(View view, PopMenuMoreItem item, int position) {
switch (item.id) {
case USER_SEARCH:
//startActivity(new Intent(this, UserSearchActivity.class));
break;
case USER_ADD:
//startActivity(new Intent(getActivity(), UserAddActivity.class));
break;
}
}
});
}
}
8、例子布局: activity_main.xml
<
?xml version=
"
1.0"
encoding=
"
utf-8"
?>
<
RelativeLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:tools=
"
http://schemas.android.com/tools"
android:id=
"
@
+
id/activity_main"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
android:paddingBottom=
"
@
dimen/activity_vertical_margin"
android:paddingLeft=
"
@
dimen/activity_horizontal_margin"
android:paddingRight=
"
@
dimen/activity_horizontal_margin"
android:paddingTop=
"
@
dimen/activity_vertical_margin"
>
<
TextView
android:id=
"
@
+
id/hello_tv"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:text=
"
Hello World!"
/>
<
/RelativeLayout>
9、所需资源文件:
文章图片
文章图片
文章图片
最近项目也蛮急的, 这里写的有点匆忙, 可能写的就没有那么具体, 希望各位朋友看的懂
借鉴: http://blog.csdn.net/maosidiaoxian/article/details/39178167
【Android 使用PopupWindow实现弹出更多的菜单】代码设置背景圆角+ 边框+ 圆半径: http://blog.csdn.net/houshunwei/article/details/17392409
推荐阅读
- android7.x Launcher3源码解析---workspace和allapps加载流程
- Android DataBinding库(MVVM设计模式)
- Android 关于java.util.NoSuchElementException错误
- Android控件介绍
- Android中Alarm的机制
- Android判断App是否在前台运行
- Android控件onClick事件
- mongodb与其它数据库的比较(它们有什么区别())
- 在Ubuntu上安装MongoDB(如何在Ubuntu中安装MongoDB())