当前位置:主页 > 移动开发 > Android代码 >

Android 使用PopupWindow实现弹出更多的菜单实例详解

时间:2020-11-28 13:31:25 | 栏目:Android代码 | 点击:

最近想要做一个弹出更多的菜单,而原生的弹出菜单却不是我们想要的效果,所以必然要自定义菜单咯。本人也是借鉴网上的资料进行封装的,感觉还蛮不错的。

原生的菜单如下图:

自定义之后的效果图:

是不是看到这里之后,对比可知,原生的效果不太理想,所以还是再自己定义吧!

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; 
 } 
} 

3、菜单项中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、所需资源文件:

参考:

android使用PopupWindow实现页面点击顶部弹出下拉菜单

您可能感兴趣的文章:

相关文章