Android 使用PopupWindow实现弹出更多的菜单
Posted 骚剑客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
代码设置背景圆角+边框+圆半径:http://blog.csdn.net/houshunwei/article/details/17392409
以上是关于Android 使用PopupWindow实现弹出更多的菜单的主要内容,如果未能解决你的问题,请参考以下文章
Android 使用PopupWindow实现弹出更多的菜单
Android-实现底部弹出PopupWindow并让背景逐渐变暗
Android-实现底部弹出PopupWindow并让背景逐渐变暗