Android 仿IOS的PopupWindow和通用BasePopupWindow搭建

简介: 截图pw.png实现1、BasePopupWindow.java1.1、实现动态加载不同layout1.2、动态配置是否弹出后背景半透明,关闭时候恢复(监听ondismiss,靠window类来变色)1.

截图

img_9fe4d71e84b6b466807c25b64eef0d6f.png
pw.png

实现

1、BasePopupWindow.java

1.1、实现动态加载不同layout
1.2、动态配置是否弹出后背景半透明,关闭时候恢复(监听ondismiss,靠window类来变色)
1.3、一些基础性的方法抽象方法
1.4、为了更加复杂的样式和动效,可以继续扩展此类

/**
 * Created by wujn on 2018/10/29.
 * Version : v1.0
 * Function: base popuwindow
 */
public abstract class BasePopupWindow extends PopupWindow implements View.OnClickListener{

    /**
     * 上下文
     */
    private Context context;
    /**
     * 最上边的背景视图
     */
    private View vBgBasePicker;
    /**
     * 内容viewgroup
     */
    private LinearLayout llBaseContentPicker;

    public BasePopupWindow(Context context) {
        super(context);
        this.context = context;
        View parentView = View.inflate(context, R.layout.base_popup_window_picker, null);
        vBgBasePicker = parentView.findViewById(R.id.v_bg_base_picker);
        llBaseContentPicker = (LinearLayout) parentView.findViewById(R.id.ll_base_content_picker);
        /***
         * 添加布局到界面中
         */
        llBaseContentPicker.addView(View.inflate(context, bindLayout(), null));
        setContentView(parentView);
        //设置PopupWindow弹出窗体的宽
        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        //设置PopupWindow弹出窗体的高
        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        //在PopupWindow里面就加上下面代码,让键盘弹出时,不会挡住pop窗口。
        this.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        setFocusable(true);//设置获取焦点
        setTouchable(true);//设置可以触摸
        setOutsideTouchable(true);//设置外边可以点击
        ColorDrawable dw = new ColorDrawable(0xffffff);
        setBackgroundDrawable(dw);
        //设置SelectPicPopupWindow弹出窗体动画效果
        this.setAnimationStyle(R.style.BottomDialogWindowAnim);
        initView(parentView);
        initListener();
        initData();
        vBgBasePicker.setOnClickListener(this);
        //是否需要屏幕半透明
        setBackgroundHalfTransition(isNeedBackgroundHalfTransition());
    }

    /**
     * 初始化布局
     *
     * @return
     */
    protected abstract int bindLayout();

    /**
     * 初始化view
     *
     * @param parentView
     */
    protected abstract void initView(View parentView);

    /**
     * 初始化数据
     */
    protected abstract void initData();

    /**
     * 初始化监听
     */
    protected abstract void initListener();





    /**
     * 为了适配7.0系统以上显示问题(显示在控件的底部)
     *
     * @param anchor
     */
    @Override
    public void showAsDropDown(View anchor) {
        if (Build.VERSION.SDK_INT >= 24) {
            Rect rect = new Rect();
            anchor.getGlobalVisibleRect(rect);
            int h = anchor.getResources().getDisplayMetrics().heightPixels - rect.bottom;
            setHeight(h);
        }
        super.showAsDropDown(anchor);
        if(isNeedBgHalfTrans){
            backgroundAlpha(0.5f);
        }
    }

    /**
     * 展示在屏幕的底部
     *
     * @param layoutid rootview
     */
    public void showAtLocation(@LayoutRes int layoutid) {
        showAtLocation(LayoutInflater.from(context).inflate(layoutid, null),
                Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
        if(isNeedBgHalfTrans){
            backgroundAlpha(0.5f);
        }
    }


    /**
     * 最上边视图的点击事件的监听
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.v_bg_base_picker:
                dismiss();
                break;
        }
    }

    /**
     * 是否设置背景半透明
     * */
    public boolean isNeedBackgroundHalfTransition(){
        return false;
    }

    private boolean isNeedBgHalfTrans = false;
    private void setBackgroundHalfTransition(boolean isNeed){
        isNeedBgHalfTrans = isNeed;
        if(isNeedBgHalfTrans){
            this.setOnDismissListener(new OnDismissListener() {
                @Override
                public void onDismiss() {
                    backgroundAlpha(1f);
                }
            });
        }
    }

    /**
     * 设置添加屏幕的背景透明度
     * @param bgAlpha
     */
    private void backgroundAlpha(float bgAlpha) {
        WindowManager.LayoutParams lp = ((Activity)context).getWindow().getAttributes();
        lp.alpha = bgAlpha; //0.0-1.0
        ((Activity)context).getWindow().setAttributes(lp);
    }


}
2、base_popup_window_picker.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="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/v_bg_base_picker"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <LinearLayout
        android:id="@+id/ll_base_content_picker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical" />
</LinearLayout>
3、进入和退出时候的动画style
<!--animanation-->
    <!-- 底部的dialog弹出的动画样式-->
    <style name="BottomDialogWindowAnim" parent="android:Animation">
        <item name="android:windowEnterAnimation">@anim/popup_bottom_enter_anim</item>
        <item name="android:windowExitAnimation">@anim/popup_bottom_exit_anim</item>
    </style>

进入动画:popup_bottom_enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="200"
        android:fromYDelta="100%p"
        android:toYDelta="0" />
    <alpha
        android:duration="200"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />
</set>

退出动画:popup_bottom_exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="200"
        android:fromYDelta="0"
        android:toYDelta="50%p" />
    <alpha
        android:duration="200"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />

</set>
4、仿IOS的layout:popup_window_album_or_camera.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="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_shape_corner_white"
        android:orientation="vertical">

        <Button
            android:id="@+id/btnCamera"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:text="拍照"
            android:textColor="@color/dodgerblue"
            android:textSize="@dimen/normal_text_size" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/gray_1" />


        <Button
            android:id="@+id/btnAlbum"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:text="从相册中选择"
            android:textColor="@color/dodgerblue"
            android:textSize="@dimen/normal_text_size" />
    </LinearLayout>


    <LinearLayout
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_shape_corner_white"
        android:orientation="vertical">

        <Button
            android:id="@+id/btnCancel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:text="@string/cancel"
            android:textColor="@color/dodgerblue"
            android:textSize="@dimen/normal_text_size" />

    </LinearLayout>

</LinearLayout>

item的背景style

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white" />
    <corners android:radius="6dp"/>
    <stroke android:width="1dp" android:color="@color/gray_1" />
</shape>
5、仿IOS的popuwindow类:AlbumOrCameraPopupWindow
public class AlbumOrCameraPopupWindow extends BasePopupWindow {

    private Button btnCamera;
    private Button btnAlbum;
    private Button btnCancel;

    private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener;
    public AlbumOrCameraPopupWindow(Context context,OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener) {
        super(context);
        this.onCameraOrAlbumSelectListener = onCameraOrAlbumSelectListener;
    }

    @Override
    public boolean isNeedBackgroundHalfTransition(){
        return true;
    }

    @Override
    protected int bindLayout() {
        return R.layout.popup_window_album_or_camera;
    }

    @Override
    protected void initView(View parentView) {
        btnCamera = (Button) parentView.findViewById(R.id.btnCamera);
        btnAlbum = (Button) parentView.findViewById(R.id.btnAlbum);
        btnCancel = (Button) parentView.findViewById(R.id.btnCancel);
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void initListener() {
        btnCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                if(onCameraOrAlbumSelectListener != null){
                    onCameraOrAlbumSelectListener.OnSelectCamera();
                }
            }
        });

        btnAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                if(onCameraOrAlbumSelectListener != null){
                    onCameraOrAlbumSelectListener.OnSelectAlbum();
                }
            }
        });

        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
    }

}

选择相机或者相册的监听接口

public interface OnCameraOrAlbumSelectListener {
    public void OnSelectCamera();
    public void OnSelectAlbum();
}
6、具体使用
private AlbumOrCameraPopupWindow ACWindow;
    private void initListener(){
        ACWindow = new AlbumOrCameraPopupWindow(this, onCameraOrAlbumSelectListener);
        btnIosPopupWindow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(ACWindow != null && !ACWindow.isShowing()){
                    ACWindow.showAtLocation(R.layout.activity_view_popup_window);
                }
            }
        });
    }

    /**选择相机或者相册*/
    private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener = new OnCameraOrAlbumSelectListener() {
        @Override
        public void OnSelectCamera() {
            LogUtil.i("OnSelectCamera...");
            ToastUtil.showShort(instance, "相机");
        }

        @Override
        public void OnSelectAlbum() {
            LogUtil.i("OnSelectAlbum...");
            ToastUtil.showShort(instance, "从相册中选择");
        }
    };

朝CV工程师又进一步~~~

目录
相关文章
|
26天前
|
安全 Android开发 iOS开发
深入探索Android与iOS的差异:从系统架构到用户体验
在当今的智能手机市场中,Android和iOS无疑是最受欢迎的两大操作系统。本文旨在探讨这两个平台之间的主要差异,包括它们的系统架构、开发环境、安全性、以及用户体验等方面。通过对比分析,我们可以更好地理解为何不同的用户群体可能会偏好其中一个平台,以及这些偏好背后的技术原因。
|
25天前
|
安全 Android开发 iOS开发
Android vs iOS:深入剖析两大移动操作系统的优劣与未来趋势####
【10月更文挑战第21天】 本文旨在通过技术视角,全面对比分析Android与iOS两大主流移动操作系统的架构差异、用户体验、安全性及生态系统等方面,探讨其各自优势与不足,并预测未来发展趋势。 ####
37 1
|
26天前
|
Java 开发工具 Android开发
Android与iOS开发环境搭建全解析####
本文深入探讨了Android与iOS两大移动操作系统的开发环境搭建流程,旨在为初学者及有一定基础的开发者提供详尽指南。我们将从开发工具的选择、环境配置到第一个简单应用的创建,一步步引导读者步入移动应用开发的殿堂。无论你是Android Studio的新手还是Xcode的探索者,本文都将为你扫清开发道路上的障碍,助你快速上手并享受跨平台移动开发的乐趣。 ####
|
15天前
|
IDE 开发工具 Android开发
移动应用开发之旅:探索Android和iOS平台
在这篇文章中,我们将深入探讨移动应用开发的两个主要平台——Android和iOS。我们将了解它们的操作系统、开发环境和工具,并通过代码示例展示如何在这两个平台上创建一个简单的“Hello World”应用。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧,帮助你更好地理解和掌握移动应用开发。
40 17
|
19天前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
25 8
|
15天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
18天前
|
人工智能 安全 物联网
Android与iOS:移动操作系统的双雄争霸
在智能手机市场中,Android和iOS作为两大主流操作系统,各自拥有庞大的用户群体和独特的生态系统。本文将深入探讨这两种系统的发展历程、技术特点、市场表现以及未来趋势,以期为读者提供全面而深入的了解。通过对比分析,我们可以发现,尽管Android和iOS在某些方面存在竞争关系,但它们也在相互借鉴中不断进步和完善。
|
15天前
|
安全 生物认证 Android开发
深入探索iOS与Android操作系统的安全性差异
本文旨在通过对比分析iOS和Android两大主流移动操作系统在安全性方面的差异,揭示它们各自的安全机制、面临的挑战以及用户如何提升自身设备的安全保护。通过对系统架构、应用审核机制、数据加密方式及隐私政策的深入探讨,本文为读者提供了一个全面了解两大平台安全性的视角,并提出了实用的安全建议。
|
19天前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
20天前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统架构差异及其对开发者的影响
本文旨在通过对比分析iOS和Android两大移动操作系统的系统架构,探讨它们在设计理念、技术实现及开发者生态方面的差异。不同于常规摘要仅概述内容要点,本摘要将简要触及核心议题,为读者提供对两大平台架构特点的宏观理解,铺垫