文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android之 弹框总结

2023-09-04 22:31

关注

一 简介

1 弹框即浮与页面之上的窗口,如键盘弹框,吐司弹框,确认弹框,下拉选择框,应用悬浮框等

2 弹框控件也很多,比如常用的Spinner,Dialog,Toast,PopWindow等,以及新增的SnackBar,DialogFragment等。

二 Spinner下拉选择使用

1 Spinner根Listview,Gridview等是同一时代的产物,所以用法也根它们差不多,主要用到BaseAdapter来加载数据源

用系统提供的Adapter,使用简单,但样式固定,数据模型固定,只能是String类型。

效果图

布局文件,添加Spinner控件

java文件设置数据源和是配置

private void initSystemAdapter(){        //设置数据源        List list = new ArrayList();        list.add("苹果");        list.add("香蕉");        list.add("橘子");        list.add("香蕉");        //设置系统适配器        ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_spinner_item,list);        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);        spinner.setAdapter(adapter);        //设置弹出偏移位置        spinner.setDropDownVerticalOffset(40);        //点击监听        spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView parent, View view, int position, long id) {                Toast.makeText(SpinnerActivity.this, list.get(position), Toast.LENGTH_SHORT).show();            }        });    }

注意:系统Adapter样式固定,有以下几种

simple_spinner_dropdown_item(列表-间距较高比较好看)
simple_spinner_item(列表-间距紧凑不好看)
simple_list_item_checked(复选框-选中的有绿沟)
simple_list_item_single_choice (单选按钮)

3 自定义适配器,灵活度高,可以设置任何类型的数据源和样式

效果图

自定义条目布局 item_fruit_list.xml

    

自定义数据源 FruitBean.java

public class FruitBean {    public String name;    public FruitBean(String name) {        this.name = name;    }}

自定义适配器CustomerAdapter.java

public class CustomerAdapter extends BaseAdapter {    private Context mContext;    private List mList;    public CustomerAdapter(Context mContext, List mList) {        this.mContext = mContext;        this.mList = mList;    }    @Override    public int getCount() {        return mList.size();    }    @Override    public Object getItem(int position) {        return mList.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder holder = null;        if (convertView == null) {            holder = new ViewHolder();            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_fruit_list, null);            holder.tvName = (TextView) convertView.findViewById(R.id.tv_name);            convertView.setTag(holder);        } else {            holder = (ViewHolder) convertView.getTag();        }        holder.tvName.setText(mList.get(position).name);        return convertView;    }    class ViewHolder {        public TextView tvName;    }}

spinner配置自定义适配器

private void initCustomerAdapter(){//设置数据源List list = new ArrayList<>();list.add(new FruitBean("苹果"));list.add(new FruitBean("香蕉"));list.add(new FruitBean("橘子"));list.add(new FruitBean("香蕉"));//设置系统适配器CustomerAdapter customerAdapter=new CustomerAdapter(this,list);spinner.setAdapter(customerAdapter);//设置弹出偏移位置spinner.setDropDownVerticalOffset(40);}

三 Dialog的使用

1 Dialog是除了Toast之外,用的最频繁的弹框,各种加载框,提示框,选择框也大都用的Dialog

2 Dialog支持任意布局,以及弹出位置,所以非常灵活。

2 示例效果图

3 创建自定义Dialog

dialog_confirm.xm

设置dialog样式custom_dialog.style,半透明度,标题,背景,弹出动画等等

需要继承系统Dialog父类

public class ConfirmDialog extends Dialog {    private Context context;    private TextView tvTitle;    private TextView tvContent;    private TextView tvCancel;    private TextView tvSure;    private String title, content, cancelString, sureString;    public interface OnViewClickLiatener {        void sureClick();        void cancelClick();    }    public OnViewClickLiatener onViewClickLiatener;    public void setOnViewClickLiatener(OnViewClickLiatener onViewClickLiatener) {        this.onViewClickLiatener = onViewClickLiatener;    }    public ConfirmDialog(Context context) {        this(context, R.style.custom_dialog);    }    public ConfirmDialog(Context context, int themeResId) {        super(context, themeResId);        this.context = context;    }    public ConfirmDialog(Context context, int themeResId, String title, String content, String cancelString, String sureString) {        super(context, themeResId);        this.context = context;        this.title = title;        this.content = content;        this.cancelString = cancelString;        this.sureString = sureString;    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.dialog_confirm);        setCanceledOnTouchOutside(true);        WindowManager.LayoutParams params = getWindow().getAttributes();        params.width = (int) (ScreenUtils.getScreenWidth((Activity) context) * 0.8f);        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;        getWindow().setGravity(Gravity.CENTER);        getWindow().setAttributes(params);        getWindow().setBackgroundDrawableResource(R.color.trans);        initView();        setData();    }    public void initView() {        tvTitle = (TextView) findViewById(R.id.tv_title);        tvContent = (TextView) findViewById(R.id.tv_content);        tvCancel = (TextView) findViewById(R.id.tv_cancel);        tvSure = (TextView) findViewById(R.id.tv_sure);    }    public void setData() {        if (!TextUtils.isEmpty(title)) {            tvTitle.setText(title);        }        if (!TextUtils.isEmpty(content)) {            tvContent.setText(content);        }        if (!TextUtils.isEmpty(cancelString)) {            tvCancel.setText(cancelString);        }        if (!TextUtils.isEmpty(sureString)) {            tvSure.setText(sureString);        }        tvCancel.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                dismiss();                if (onViewClickLiatener != null) {                    onViewClickLiatener.cancelClick();                }            }        });        tvSure.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                dismiss();                if (onViewClickLiatener != null) {                    onViewClickLiatener.sureClick();                }            }        });    }    @Override    public void dismiss() {        super.dismiss();    }}

使用

     ConfirmDialog showCancelDialog;    public void showCancelDialog(String reportOrderNo, String storeCode) {        if (showCancelDialog == null) {            showCancelDialog = new ConfirmDialog(activity, "取消提醒", "取消后将不再对已添加的内容进行保存", "暂不取消", "确认取消");            showCancelDialog.setOnViewClickLiatener(new ConfirmDialog.OnViewClickLiatener() {                @Override                public void sureClick() {                    if (TextUtils.isEmpty(reportOrderNo)) {                        activity.finish();                    } else {                        httpReportOrderCancel(reportOrderNo, storeCode);                    }                }                @Override                public void cancelClick() {                }            });        }        if (!showCancelDialog.isShowing()) {            showCancelDialog.show();        }    }

4 设置认为位置的dialog,如下效果图在屏幕右上角,并且有偏移距离

 根正常Dialog使用一样,不过在构造函数里面需要传一个view,即对于那个view弹出,通过获取view在屏幕的位置,来设置Dialog的偏移位置。如下示例

public class OtherUserMainMoreDialog extends Dialog {    private DialogViewListener listener;    private Activity mContext;    private View locationView;    private LinearLayout llRemarks;    private LinearLayout llPullBlack;    private LinearLayout llDeleteFriend;    public interface DialogViewListener {        void remarksClick();        void pullBlackClick();        void deleteFriend();    }    public OtherUserMainMoreDialog(Activity context) {        super(context);        mContext = context;    }    public void setDialogViewListener(DialogViewListener listener) {        this.listener = listener;    }    public OtherUserMainMoreDialog(Activity context, int themeResId, View locationView) {        super(context, themeResId);        mContext = context;        this.locationView = locationView;    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        View view = LayoutInflater.from(mContext).inflate(R.layout.dialog_other_more, null);        setContentView(view);        //设置Dialog点击外部消失        setCanceledOnTouchOutside(true);        setCancelable(true);        //获取控件 textview 的绝对坐标,( y 轴坐标是控件上部到屏幕最顶部(不包括控件本身))        //location [0] 为x绝对坐标;location [1] 为y绝对坐标        int[] location = new int[2];        locationView.getLocationInWindow(location); //获取在当前窗体内的绝对坐标        //获取当前Activity所在的窗体        Window window = getWindow();        WindowManager.LayoutParams wlp = window.getAttributes();        //获取通知栏高度  重要的在这,获取到通知栏高度        int notificationBar = Resources.getSystem().getDimensionPixelSize(                Resources.getSystem().getIdentifier("status_bar_height", "dimen", "android"));        wlp.x = location[0];//对 dialog 设置 x 轴坐标        wlp.y = location[1] + locationView.getHeight() - notificationBar - 15; //对dialog设置y轴坐标        wlp.gravity = Gravity.TOP;        wlp.width = WindowManager.LayoutParams.MATCH_PARENT;        window.setAttributes(wlp);        llRemarks = (LinearLayout) findViewById(R.id.ll_remarks);        llPullBlack = (LinearLayout) findViewById(R.id.ll_pull_black);        llDeleteFriend = (LinearLayout) findViewById(R.id.ll_delete_friend);        llPullBlack.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                if (listener != null) {                    listener.pullBlackClick();                }                cancel();            }        });        llRemarks.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                if (listener != null) {                    listener.remarksClick();                }                cancel();            }        });        llDeleteFriend.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                if (listener != null) {                    listener.deleteFriend();                }                cancel();            }        });    }}

5 DIalog使用注意:

由于DIalog必须依赖与一个Activty,如果Activity意外销毁,那Dialog再去弹出或者消息就会找不到该Activity,从而发生崩溃。解决方法如下:

  • 把Activity设置为弱引用,以便Activity销毁时,持有Activity的对象能够及时回收。
  • 在Dialog弹出消息前判断是否Activity存活,从而保证安全弹出或者消息

如下处理:

@Overridepublic void dismiss() {if (context == null || ((Activity) context).isDestroyed() || ((Activity) context).isFinishing()) {return;}super.dismiss();}@Overridepublic void show() {if (context == null || ((Activity) context).isDestroyed() || ((Activity) context).isFinishing()) {return;}super.show();}

四,Toast的使用

1 最简单使用,调用系统api

Toast.makeText(context, "提示消息", Toast.LENGTH_SHORT).show();

2 设置Toast的位置,顶部,中间,底部等位置

Toast toast = Toast.makeText(context, "提示消息", Toast.LENGTH_SHORT);toast.setGravity(Gravity.TOP, 0, 0);toast.show();

3 控制短时间内弹出频率

 private static String oldMsg;    protected static Toast toast = null;    private static long oneTime = 0;    private static long twoTime = 0;    public static void showToast(Context context, String s, int gravity, int offX, int offY) {        if (toast == null) {            toast = Toast.makeText(context, s, Toast.LENGTH_SHORT);            toast.setGravity(gravity, offX, offY);            toast.show();            oneTime = System.currentTimeMillis();        } else {            twoTime = System.currentTimeMillis();            if (s.equals(oldMsg)) {                if (twoTime - oneTime > Toast.LENGTH_SHORT) {                    toast.show();                }            } else {                oldMsg = s;                toast.setText(s);                toast.show();            }        }        oneTime = twoTime;    }

4 自定义Toast布局样式

 private static TextView textView;        public static void showPicToast(Context context, String text) {        if (toast == null) { // 1. 创建前 2.消失后toast为null            // 获取打气筒            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);            //创建视图            View view = inflater.inflate(R.layout.toast_bg, null);            textView = (TextView) view.findViewById(R.id.tv_toast_text);            //创建土司            toast = new Toast(context);            //设置居中方式  默认在底部            //toast.setGravity(Gravity.CENTER, 0, 0);//如果不设置剧中方式,使用系统默认的吐司位置            //设置土司的持续时长            toast.setDuration(Toast.LENGTH_SHORT);            toast.setGravity(Gravity.CENTER, 0, 0);            //设置土司的背景View            toast.setView(view);        }        //设置土司的显示额内容        textView.setText(text);        toast.show();    }

5 使用注意:

Android 30之后Toast位置参数将失效,设置位置也会跟随系统的位置,所以Google建议用SnackBar来替换Toast。

如果坚持用Toast那么推荐一个Toast库,可以设置Toast位置,如下添加依赖库

implementation 'com.hjq:toast:8.8'

在application里面初始化

ToastUtils.init(this);

在其它位置弹出该Toast

ToastUtils.show("提示消息");

五 SnackBar

2 简单使用

 public void snackbar1(View view) {   Snackbar.make(this,llRootLayout,"snack bar",Snackbar.LENGTH_SHORT).show();}

第一个参数是Context 
第二个参数是要显示的view
第三个参数是显示的字符串
第四个参数是显示时长,时长有下面三种:
Snackbar.LENGTH_SHORT与Toast.LENGHT_SHORT(大约1秒多)一样显示较短时长后自动消失
Snackbar.LENGTH_LONG与Toast.LENGHT_LONG(大约3秒)一样显示相对较长时间后自动消失
Snackbar.LENGTH_INDEFINITE:永不消失除非手动调用dismiss()方法去除Snackbar

3 交互使用

public void snackbar2(View view) {Snackbar snack_bar = Snackbar.make(this,view, "确定退出吗?", Snackbar.LENGTH_INDEFINITE);snack_bar.setAction("确认", new View.OnClickListener() {@Overridepublic void onClick(View v) {//退出}});snack_bar.show();}

4 自定义布局SnackBar

布局snackbar_view.xml

            

工具类SnackBarUtil.java 

public class SnackBarUtil {    //自定义 SnackBar 布局    public static void show(Activity activity, View view, String msg, String action, SnackBarOnClick listener) {        //获取示例 findViewById(android.R.id.content) //LENGTH_LONG/LENGTH_SHORT: 会自动消失 LENGTH_INDEFINITE: 需要手动点击消失        Snackbar snackbar = Snackbar.make(view, "", Snackbar.LENGTH_SHORT);        //设置 Snackbar 的深度,避免被其他控件遮挡        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {            snackbar.getView().setElevation(0);        }        //设置背景透明,避免自带黑色背景影响        snackbar.getView().setBackgroundColor(Color.TRANSPARENT);        //设置padding 取消自定义时黑色边框        snackbar.getView().setPadding(0, 0, 0, 0);        Snackbar.SnackbarLayout snackbarLayout = (Snackbar.SnackbarLayout) snackbar.getView();        //设置SnackBar的显示位置        //ViewGroup.LayoutParams layoutParams = snackbarLayout.getLayoutParams();        FrameLayout.LayoutParams flp = new FrameLayout.LayoutParams(dip2px(activity,260),dip2px(activity,32)); // 将原来Snackbar的宽高传入新的LayoutParams        flp.gravity = Gravity.CENTER | Gravity.BOTTOM; // 设置显示位置        flp.bottomMargin = dip2px(activity,8);        ((View) snackbarLayout).setLayoutParams(flp);        //获取自定义布局        View inflate = LayoutInflater.from(activity).inflate(R.layout.snackbar_view, null);        //获取布局内控件        TextView textView = inflate.findViewById(R.id.textView);        //TextView 前边添加图片        //Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher_round);//图片自己选择        //drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());        //textView.setCompoundDrawables(drawable, null, null, null);        //增加文字和图标的距离        //textView.setCompoundDrawablePadding(20);        //设置文本        textView.setText(msg);        if (action != null && listener != null) {            TextView textViewSub = inflate.findViewById(R.id.textViewSub);            textViewSub.setVisibility(View.VISIBLE);            textViewSub.setText(action);            textViewSub.setOnClickListener(v -> {                if (listener != null) {                    listener.clickEvent(snackbar);                }            });        }        //添加图片 获取布局内控件        //ImageView imageView = inflate.findViewById(R.id.imageView2);        //获取图片资源        //Drawable drawable = activity.getResources().getDrawable(closeIcon);        //设置图片        //imageView.setImageDrawable(drawable);        //将自定义布局添加到 Snackbar 中        snackbarLayout.addView(inflate);        //显示        snackbar.show();    }    public interface SnackBarOnClick {        void clickEvent(Snackbar snackbar);    }        public static int dip2px(Activity activity, float dpValue) {        final float scale = activity.getResources().getDisplayMetrics().density;        return (int) (dpValue * scale + 0.5f);    }}

 调用工具类SnackBarUtil

public void snackbar3(View view) {        SnackBarUtil.show(this, view, "确定退出吗?", "确认", new SnackBarUtil.SnackBarOnClick() {            @Override            public void clickEvent(Snackbar snackbar) {                //退出            }        });    }

六 PopWindow下拉弹框使用

1 PopWindow也是一种弹框,相比较Dialog它更多的使用场景是基于某个控件位置的弹出,也支持任意布局和样式

2 示例,添加布局文件,popup_size_listview.xml

    

3 自定义PopupWindow

public class PopupviewSizeModel extends PopupWindow {    private IPopuWindowListener mOnClickListener;    private Activity mContext;    private RecyclerView recyclerView;    private PopupModelListAdapter popupModelListAdapter;    private List listString=new ArrayList<>();        public void setPopuWindowListener(IPopuWindowListener mOnClickListener) {        this.mOnClickListener = mOnClickListener;    }    public PopupviewSizeModel(Activity context) {        super(context);        this.mContext = context;        //获取布局文件        View mContentView = LayoutInflater.from(mContext).inflate(R.layout.popup_size_listview, null);        initView(mContentView);        //设置布局        setContentView(mContentView);        int width = context.getWindowManager().getDefaultDisplay().getWidth();        setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);        setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);        //设置可以点击外部消息        //开始        setOutsideTouchable(true);        setFocusable(true);//        setBackgroundDrawable(new BitmapDrawable());        setBackgroundDrawable(context.getResources().getDrawable(android.R.color.transparent));        setAnimationStyle(R.style.pop_animation);    }    private void initView(View contentView) {        recyclerView = (RecyclerView) contentView.findViewById(R.id.rcl_view);        LinearLayoutManager manager = new LinearLayoutManager(mContext);        recyclerView.setLayoutManager(manager);        recyclerView.setNestedScrollingEnabled(false);        popupModelListAdapter = new PopupModelListAdapter(mContext, R.layout.item_popup_size_list, listString);        recyclerView.setAdapter(popupModelListAdapter);        popupModelListAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() {            @Override            public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {                dismiss();                if(mOnClickListener!=null){                    mOnClickListener.onItemClick(position);                }            }            @Override            public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {                return false;            }        });    }    public void setListData(List list) {        listString.clear();        listString.addAll(list);        popupModelListAdapter.setData(listString);        popupModelListAdapter.notifyDataSetChanged();    }//     /     * 在android7.0上,如果不主动约束PopuWindow的大小,比如,设置布局大小为 MATCH_PARENT,那么PopuWindow会变得尽可能大,以至于 view下方无空间完全显示PopuWindow,而且view又无法向上滚动,此时PopuWindow会主动上移位置,直到可以显示完全。//     * 解决办法:主动约束PopuWindow的内容大小,重写showAsDropDown方法://     * @param anchor//     *///    @Override//    public void showAsDropDown(View anchor,int xoff,int yoff,int gravity) {//        if (Build.VERSION.SDK_INT >= 24) {//            Rect visibleFrame = new Rect();//            anchor.getGlobalVisibleRect(visibleFrame);//            int height = anchor.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom;//            setHeight(height);//            showAsDropDown(anchor, xoff, yoff,gravity);//        } else {//           showAsDropDown(anchor, xoff, yoff,gravity);//        }//        super.showAsDropDown(anchor);//    }    public interface IPopuWindowListener {        void onItemClick(int position);    }}

4 设置数据模型 

publicclass BindSizeListDTO{        public String id;        public String name;        public BindSizeListDTO(String name) {            this.name = name;        }    }

5 在指定view位置弹出该PopupWindow

private PopupviewSizeModel popupviewModelSize;List listStringSize = new ArrayList<>();private void showSizePopup() {listStringSize.add(new InfoBean.BindSizeListDTO("230x150"));listStringSize.add(new InfoBean.BindSizeListDTO("270x200"));listStringSize.add(new InfoBean.BindSizeListDTO("300x200"));listStringSize.add(new InfoBean.BindSizeListDTO("330x225"));listStringSize.add(new InfoBean.BindSizeListDTO("340x239"));if (popupviewModelSize == null) {popupviewModelSize = new PopupviewSizeModel(mContext);popupviewModelSize.setPopuWindowListener(new PopupviewSizeModel.IPopuWindowListener() {@Overridepublic void onItemClick(int position) {Toast.makeText(SnackBarActivity.this, "点击了条目", Toast.LENGTH_SHORT).show();}});}popupviewModelSize.setListData(listStringSize);popupviewModelSize.showAsDropDown(tvSize);}

七 DialogFragment

1 Dialog是依赖与Activity的生命周期,DialogFragment与Dialog不同的是它本质上是一个Fragment,也就具有Fragment所拥有的生命周期,

1 创建DialogFragment的方式,用onCreateDialog来创建系统提供的Dialog

public class SystemDialogFragment extends DialogFragment {    @NonNull    @Override    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {        AlertDialog dialog = new AlertDialog.Builder(getContext())                .setTitle("系统弹窗")                .setMessage("信息")                //.setIcon(R.drawable.assign_set_question_ic_v2)                .setNegativeButton("取消", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                    }                }).setPositiveButton("确定", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        Toast.makeText(getContext(), "确认", Toast.LENGTH_SHORT).show();                    }                }).create();        return dialog;    }}

Activity中调用该DialogFragment

public class DialogFragmentActivity extends ComponentActivity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activty_dialog_fragment);    }    public void alertdialog(View view) {        SystemDialogFragment systemDialogFragment=new SystemDialogFragment();        systemDialogFragment.show(getFragmentManager(),"ss");    }}

效果:

2 自定义布局DialogFragment

创建布局文件dialog_confirm.xml

                                

创建DialogFragment,CustomerDialogFragment.java

public class CustomerDialogFragment extends DialogFragment {    public View mRootView;    private TextView tvTitle;    private TextView tvContent;    private TextView tvCancel;    private TextView tvSure;    @Nullable    @Override    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        if (mRootView == null){            //获取布局            mRootView = inflater.inflate(R.layout.dialog_confirm,container,false);        }        tvTitle = (TextView) mRootView.findViewById(R.id.tv_title);        tvContent = (TextView) mRootView.findViewById(R.id.tv_content);        tvCancel = (TextView) mRootView.findViewById(R.id.tv_cancel);        tvSure = (TextView) mRootView.findViewById(R.id.tv_sure);        tvCancel.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dismiss();            }        });        tvSure.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(getActivity(), "点击确定", Toast.LENGTH_SHORT).show();                dismiss();            }        });        return mRootView;    }}

Activity调用该DialogFragment

 public void customerdialog(View view) {     CustomerDialogFragment systemDialogFragment=new CustomerDialogFragment();     systemDialogFragment.show(getFragmentManager(),"Customer"); }

效果演示

八 系统悬浮框

1 系统悬浮框跟随应用生命周期,可以不在Acitivity上面,不依赖Acitivity,适合全局生命周期的弹框

2 使用,新建布局文件,float_layout_window.xml

                        

2 添加悬浮框权限

3 新建FloatWindowsActivity.java,添加悬浮框布局

public class FloatWindowsActivity extends ComponentActivity {    public WindowManager mWindowManager;    public View mWindowView;    public LinearLayout mText;    public WindowManager.LayoutParams wmParams;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activty_float_windows);    }    public void folatwindows(View view) {        checkFloatPermission();    }    @Override    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if(requestCode==0){            checkFloatPermission();        }    }        public void checkFloatPermission(){        if(!Settings.canDrawOverlays(FloatWindowsActivity.this)) {            Toast.makeText( FloatWindowsActivity.this, "当前无权限,请授权", Toast.LENGTH_SHORT);            startActivityForResult( new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse( "package:"+ getPackageName())), 0);        }else {            initWindowParams();        }    }        private void initWindowParams() {        //1,获取系统级别的WindowManager        mWindowManager = (WindowManager) getApplication().getSystemService(getApplication().WINDOW_SERVICE);        wmParams = new WindowManager.LayoutParams();        //2,添加系统参数,确保悬浮框能显示到手机上        //电话窗口。它用于电话交互(特别是呼入)。它置于所有应用程序之上,状态栏之下。        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;        } else {            wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;        }        // flag 设置 Window 属性        wmParams.flags                |= WindowManager.LayoutParams.FLAG_FULLSCREEN                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;        //期望的位图格式。默认为不透明        wmParams.format = PixelFormat.TRANSLUCENT;        //不许获得焦点        wmParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;        //窗口停靠位置        wmParams.gravity = Gravity.LEFT | Gravity.TOP;        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;        wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;        addWindowViewZWindow();        initClick();    }        private void addWindowViewZWindow() {        if(mWindowView==null){            mWindowView = LayoutInflater.from(getApplication()).inflate(R.layout.float_layout_window, null);            mText = (LinearLayout) mWindowView.findViewById(R.id.linear);        }        mWindowManager.addView(mWindowView, wmParams);    }        int mStartX, mStartY;    int mEndX, mEndY;    private void initClick() {        mText.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()) {                    //按下鼠标的时候记录下屏幕的位置                    case MotionEvent.ACTION_DOWN:                        mStartX = (int) event.getRawX();                        mStartY = (int) event.getRawY();                        break;                    case MotionEvent.ACTION_MOVE:                        mEndX = (int) event.getRawX();                        mEndY = (int) event.getRawY();                        if (needIntercept()) {//getRawX是触摸位置相对于整个屏幕的位置,getX是控触摸点相对于控件最左边的位置wmParams.x = (int) event.getRawX() - mWindowView.getMeasuredWidth() / 2;wmParams.y = (int) event.getRawY() - mWindowView.getMeasuredHeight() / 2;mWindowManager.updateViewLayout(mWindowView, wmParams);return true;                        }                        break;                    case MotionEvent.ACTION_UP:                        if (needIntercept()) {return true;                        }                        break;                }                return false;            }        });        mText.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(FloatWindowsActivity.this, "点击悬浮框", Toast.LENGTH_SHORT).show();            }        });    }        private boolean needIntercept() {        if (Math.abs(mStartX - mEndX) > 30 || Math.abs(mStartY - mEndY) > 30) {            return true;        }        return false;    }}

4 效果图

可以在任意Activity显示

 也可以退到桌面仍显示

来源地址:https://blog.csdn.net/qq_29848853/article/details/131057663

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯