自定义PopupWindow实现下拉菜单选项效果

         在android 项目中,有时候我们要用到下拉菜单的效果,比如,如下,这种界面,这时候,我们就可以用自定义PopupWindow的方式来实现这种功能了。下实例还带了一个界面透明度变化的功能。



自定义PopupWindow实现下拉菜单选项效果_第1张图片

首先我们自定义一个平滑过渡透明度的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>


你可能感兴趣的:(android,基础)