在android 项目中,有时候我们要用到下拉菜单的效果,比如,如下,这种界面,这时候,我们就可以用自定义PopupWindow的方式来实现这种功能了。下实例还带了一个界面透明度变化的功能。
首先我们自定义一个平滑过渡透明度的popupWindow,实现打开popupWidow背景透明值变化的效果
public class StyleAlphaPopWindow extends PopupWindow { //ValueAnimator会从1平滑过渡到0的值的效果 private ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(500); public StyleAlphaPopWindow(View contentView, int width, int height, boolean focusable) { super(contentView, width, height, focusable); setBackgroundDrawable(new ColorDrawable(-0x90000000));//设置背景半透明 update();//刷新update()在以下状态下要更新 ,This include: setClippingEnabled(boolean), setFocusable(boolean), setIgnoreCheekPress(),setInputMethodMode(int), setTouchable(boolean), and setAnimationStyle(int). setTouchable(true);// 设置PopupWindow可触摸 setOutsideTouchable(true);// 设置允许在外点击消失 contentView.setFocusableInTouchMode(true);//调用View的setFocusableInTouchMode(true)可以使View在Touch Mode模式之下仍然可获得焦点 } @Override public void showAtLocation(View parent, int gravity, int x, int y) { super.showAtLocation(parent, gravity, x, y); showTransBackground(true); } @Override public void showAsDropDown(View anchor) { super.showAsDropDown(anchor); showTransBackground(true); } public void showTransBackground(final boolean isTrans) { final Window window = ((Activity) getContentView().getContext()).getWindow(); if (window == null) { return; } valueAnimator.removeAllListeners(); valueAnimator.removeAllUpdateListeners(); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float fraction = (float) animation.getAnimatedValue(); WindowManager.LayoutParams lp = window.getAttributes(); if (isTrans) { lp.alpha = 0.7f + 0.3f * fraction;//从不透明平滑过渡到0.7 } else { lp.alpha = 0.7f + (1 - fraction) * 0.3f;//从0.7平滑过渡到不透明 } window.setAttributes(lp); } }); valueAnimator.start(); } }
然后定义一个子类继承它,
public class MenuItemPopWindow extends StyleAlphaPopWindow { /** * 个人中心 */ public static final byte MENU_TYPE_PERSION = 0x1; /** * 新增一个 */ public static final byte MENU_TYPE_ADDED = 0x2; /** * 删除 */ public static final byte MENU_TYPE_DELETE = 0x4; /** * 分享 */ public static final byte MENU_TYPE_SHARE = 0x8; public MenuItemPopWindow(Context context, byte flag, final MenuItemListenr lis) { super(LayoutInflater.from(context).inflate(R.layout.popwin_desc_top_menu_item, null), ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); Drawable drawable = context.getResources().getDrawable(R.drawable.popmenu_bg); setBackgroundDrawable(drawable); View view = getContentView().findViewById(R.id.tv_menu_person); if ((flag & MENU_TYPE_PERSION) != 0) {//点击个人中心选项事件处理 view.setVisibility(View.VISIBLE); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != lis) { lis.onItem(MENU_TYPE_PERSION); } } }); } view = getContentView().findViewById(R.id.tv_menu_added); if ((flag & MENU_TYPE_ADDED) != 0) {//新增一个 view.setVisibility(View.VISIBLE); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != lis) { lis.onItem(MENU_TYPE_ADDED); } } }); } view = getContentView().findViewById(R.id.tv_menu_delete); if ((flag & MENU_TYPE_DELETE) != 0) {//删除 view.setVisibility(View.VISIBLE); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != lis) { lis.onItem(MENU_TYPE_DELETE); } } }); } view = getContentView().findViewById(R.id.tv_menu_share); if ((flag & MENU_TYPE_SHARE) != 0) {//分享 view.setVisibility(View.VISIBLE); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != lis) { lis.onItem(MENU_TYPE_SHARE); } } }); } setOnDismissListener(new OnDismissListener() {//点击空白消失监听 @Override public void onDismiss() { showTransBackground(false); } }); } /** * 创建实例 * @param context * @param flag * @param lis * @return */ public static MenuItemPopWindow builder(Context context, byte flag, MenuItemListenr lis) { return new MenuItemPopWindow(context, flag, lis); } /** * 回调监听 */ public interface MenuItemListenr { void onItem(byte flag); } }然后是acitvity代码,这里有一个处理技巧,
byte bFlag = 0; bFlag |= MenuItemPopWindow.MENU_TYPE_PERSION; bFlag |= MenuItemPopWindow.MENU_TYPE_ADDED; bFlag |= MenuItemPopWindow.MENU_TYPE_DELETE; bFlag |= MenuItemPopWindow.MENU_TYPE_SHARE;
十六进制转化为二进制
1 是0001
2是0010
4是0100
8是1000
与0000做或的判断
或1有一个是1得1,与0有一个是0得0。
0000|0001=0001,0001|0010=0011, 0011|0100=0111,0111|1000=1111,转成十进制是15。
然后if ((flag & MENU_TYPE_PERSION) != 0) {//点击个人中心选项事件处理 view.setVisibility(View.VISIBLE); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != lis) { lis.onItem(MENU_TYPE_PERSION); } } }); }
或的情况下与1,2,4,8是不管怎么计算都会得到1111(还可以拓展成与16进制10的与计算,也是会得到1111).然后再与1,2,4,8做与计算,不管怎么都不会等于0,来实现开始是全部不可见,后面全部可见的功能。
activity代码public class CustomPopupWindowActivity extends Activity { private Button btnPopupWindow; private MenuItemPopWindow mMenuItemPop; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_custom_popup_window); btnPopupWindow = (Button) findViewById(R.id.btn_popup_window); btnPopupWindow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { openMenuPopWindow(); } }); } /** * 打开菜单项popupWindow */ private void openMenuPopWindow() { if (null == mMenuItemPop) { byte bFlag = 0; bFlag |= MenuItemPopWindow.MENU_TYPE_PERSION; bFlag |= MenuItemPopWindow.MENU_TYPE_ADDED; bFlag |= MenuItemPopWindow.MENU_TYPE_DELETE; bFlag |= MenuItemPopWindow.MENU_TYPE_SHARE; mMenuItemPop = MenuItemPopWindow.builder(this, bFlag, new MenuItemPopWindow.MenuItemListenr() { @Override public void onItem(byte flag) { switch (flag) { case MenuItemPopWindow.MENU_TYPE_PERSION: Toast.makeText(CustomPopupWindowActivity.this, "个人中心", Toast.LENGTH_LONG).show(); break; case MenuItemPopWindow.MENU_TYPE_ADDED:// Toast.makeText(CustomPopupWindowActivity.this, "再设计一个", Toast.LENGTH_LONG).show(); break; case MenuItemPopWindow.MENU_TYPE_DELETE: Toast.makeText(CustomPopupWindowActivity.this, "删除", Toast.LENGTH_LONG).show(); break; case MenuItemPopWindow.MENU_TYPE_SHARE: Toast.makeText(CustomPopupWindowActivity.this, "分享", Toast.LENGTH_LONG).show(); break; } mMenuItemPop.dismiss(); } }); } if (null != mMenuItemPop) { mMenuItemPop.showAsDropDown(btnPopupWindow); } } }
图中的黑色背景效果popmenu_bg是用9.png图片实现的,不懂的同学可以先百度下9,png图片的做法。
activity中布局文件activity_custom_popup_window.xml
<LinearLayout 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:orientation="vertical" > <Button android:id="@+id/btn_popup_window" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="打开popupWindow" /> LinearLayout>
popupwindow的布局文件,popwin_desc_top_menu_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp"> <TextView android:id="@+id/tv_menu_person" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawablePadding="20dp" android:gravity="center_vertical" android:padding="10dp" android:text="个人中心" android:textColor="@color/whiteColor" android:textSize="16sp" android:visibility="gone"/> <TextView android:id="@+id/tv_menu_added" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawablePadding="20dp" android:gravity="center_vertical" android:padding="10dp" android:text="再设计一个" android:textColor="@color/whiteColor" android:textSize="16sp" android:visibility="gone"/> <TextView android:id="@+id/tv_menu_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawablePadding="20dp" android:gravity="center_vertical" android:padding="10dp" android:text="删除" android:textColor="@color/whiteColor" android:textSize="16sp" android:visibility="gone"/> <TextView android:id="@+id/tv_menu_share" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawablePadding="20dp" android:gravity="center_vertical" android:padding="10dp" android:text="分享" android:textColor="@color/whiteColor" android:textSize="16sp" android:visibility="gone"/> LinearLayout>