[Android]自定义Dialog发现了一个BUG,不知道怎么解决了

__椎名真白 2018-04-13 07:13:09
这样的啊,我这几天仿IOS,设计了一个对话框。如果说内容短、显示的List短,完全没有问题。测试的时候也是这么测试的,但是实际使用的时候,我发现如果内容过长或者填充的List长度很大的时候,中间弹窗不会显示取消、确定按钮,底部弹窗不会显示取消按钮。迷茫中。
自定义的Dialog:https://blog.csdn.net/Lone1yCode/article/details/79927873
BUG 1 : 中间弹窗,内容过长时,无法滑动。加了一个ScrollView,已解决。
BUG 2:不管是中间弹窗还是底部弹窗,内容过长或者List过长时,不会显示底部的按钮。
正常情况下:


一旦内容过长:


这是什么意思?都在同一个布局中,为什么还有这种情况?给根布局加一个ScrollView?这样确实可以解决问题,但是更新了一个bug,新增了N个bug,ListView会只显示一行,虽然可以滑动;替换布局不再生效。
怎么改才合适呢?期望效果是内容过长时,内容区可滑动,底部按钮一定要显示
就像默认的对话框效果一样:


求助攻。。。

...全文
1181 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 3 楼 z979451341 的回复:
再用scrollView包一层就好
不可以啊,如果内容是文本,设置最大高度,怎么嵌套ScrollView都是无法滑动的。如果内容是List,他会把原有的TextView替换掉,List没有MaxHeight属性,又会回到最开始的问题,过长就不会显示底部按钮
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
再用scrollView包一层就好
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
明显可以把内容布局设置最大高度
__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 24 楼 z979451341 的回复:
再改一下,把获取ListView高度的函数换一个,然后获取设备高度的函数,你那个有问题,也换一个 首先是build函数


                int list_height ;

                list_height = getMsgListViewHeight(listView);

                Log.v("zzw", list_height +"");
                WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
                int width = wm.getDefaultDisplay().getWidth();
                int height = wm.getDefaultDisplay().getHeight();
                if (list_height > height*3/5) {
                    list_height = height*3/5;
                }


                LinearLayout.LayoutParams LayoutParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT, list_height);
                ((ScrollView) mDialogLayout.findViewById(R.id.sv)).setLayoutParams(LayoutParams);


    private int getMsgListViewHeight(ListView mMessageCenterLv) {
        int totalHeight = 0;

        ListAdapter listAdapter = mMessageCenterLv.getAdapter();
        if (listAdapter == null) {
            return totalHeight;
        }

        int height = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, mMessageCenterLv);
            int desiredWidth = View.MeasureSpec.makeMeasureSpec(mMessageCenterLv.getWidth(), View.MeasureSpec.AT_MOST);
            listItem.measure(desiredWidth, 0);
            height += (listItem.getMeasuredHeight());
        }

        totalHeight = height + (mMessageCenterLv.getDividerHeight() * (listAdapter.getCount() - 1));
        return totalHeight;
    }
嗯呐,这么改是可以的,List可以正常显示了,但是注释了自定义的MyDialogScrollView的onMesure方法,中间弹窗内容过长的时候,还是无法显示底部按钮,这个TextView的高度不好测吧。能不能在最后构建Dialog的时候,判断弹窗的高度,然后设置一个小一点的高度值。如果内容是可以滑动的,应该不会有内容丢失的问题吧。。
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
再改一下,把获取ListView高度的函数换一个,然后获取设备高度的函数,你那个有问题,也换一个 首先是build函数


                int list_height ;

                list_height = getMsgListViewHeight(listView);

                Log.v("zzw", list_height +"");
                WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
                int width = wm.getDefaultDisplay().getWidth();
                int height = wm.getDefaultDisplay().getHeight();
                if (list_height > height*3/5) {
                    list_height = height*3/5;
                }


                LinearLayout.LayoutParams LayoutParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT, list_height);
                ((ScrollView) mDialogLayout.findViewById(R.id.sv)).setLayoutParams(LayoutParams);


    private int getMsgListViewHeight(ListView mMessageCenterLv) {
        int totalHeight = 0;

        ListAdapter listAdapter = mMessageCenterLv.getAdapter();
        if (listAdapter == null) {
            return totalHeight;
        }

        int height = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, mMessageCenterLv);
            int desiredWidth = View.MeasureSpec.makeMeasureSpec(mMessageCenterLv.getWidth(), View.MeasureSpec.AT_MOST);
            listItem.measure(desiredWidth, 0);
            height += (listItem.getMeasuredHeight());
        }

        totalHeight = height + (mMessageCenterLv.getDividerHeight() * (listAdapter.getCount() - 1));
        return totalHeight;
    }
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
高度好了,我改了两个类 首先注释掉MyDialogScrollView的onMeasure方法 然后修改MyDialog的两个函数

    public Dialog builder() {
        dialog = new Dialog(mContext, R.style.MyDialogTheme);
        dialog.setCancelable(mCancelable);
        dialog.addContentView(mDialogLayout, new ActionBar.LayoutParams(
                ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.MATCH_PARENT));
        //如果是中间弹窗
        if (!mIsBottomDialog) {
            //如果没有设置Title
            if (!mIsShowTitle) {
                mDialogLayout.findViewById(R.id.title_background).setVisibility(View.GONE);
            }
            //如果设置显示了ListView
            if (mIsShowListView) {
                ListView listView = new ListView(mContext);
                LinearLayout.LayoutParams listLayoutParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
                listView.setLayoutParams(listLayoutParams);
                listView.setAdapter(mAdapter);

                int list_height = measureListViewWrongHeight(listView) * listView.getCount();

                if (list_height > 500) {
                    list_height = 500;
                }

                LinearLayout.LayoutParams LayoutParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT, list_height);
                ((ScrollView) mDialogLayout.findViewById(R.id.sv)).setLayoutParams(LayoutParams);

                setView(listView);
                if (mItemClickListener != null) {
                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            mItemClickListener.onItemClick(parent, view, position, id);
                            dialog.dismiss();
                        }
                    });
                } else {
                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            dialog.dismiss();
                        }
                    });
                }





            }
            //如果设置了negative区域的按钮
            if (mIsShowNegativeButton) {
                if (negativeButton != null) {
                    mDialogLayout.findViewById(R.id.negative).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            negativeButton.onClick(v);
                            dialog.dismiss();
                        }
                    });
                } else {
                    mDialogLayout.findViewById(R.id.negative).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                }
            } else {
                mDialogLayout.findViewById(R.id.negative).setVisibility(View.GONE);
                mDialogLayout.findViewById(R.id.line3).setVisibility(View.GONE);
            }
            //如果设置了positive区域的按钮
            if (mIsShowPositiveButton) {
                if (positiveButton != null) {
                    mDialogLayout.findViewById(R.id.positive).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            positiveButton.onClick(v);
                            dialog.dismiss();
                        }
                    });
                } else {
                    mDialogLayout.findViewById(R.id.positive).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                }
            } else {
                mDialogLayout.findViewById(R.id.positive).setVisibility(View.GONE);
                mDialogLayout.findViewById(R.id.line3).setVisibility(View.GONE);
            }
            mDialogLayout.findViewById(R.id.negative).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (negativeButton != null) {
                        negativeButton.onClick(v);
                    }
                    dialog.dismiss();
                }
            });
            //如果有自定义的动画效果传入,就显示传入的动画效果,否则显示默认效果,另外:传入0,无动画
            if (mIsHaveCustomAnim) {
                if (mCustomAnim != 0) { //设置显示dialog的显示动画
                    dialog.getWindow().setWindowAnimations(mCustomAnim);
                }
            } else {                    //设置默认dialog的显示动画
                dialog.getWindow().setWindowAnimations(R.style.DialogInAndOutAnim);
            }
        } else { //是底部弹窗
            //如果没有设置底部弹窗标题
            if (!mIsShowBottomTitle) {
                mDialogLayout.findViewById(R.id.bottom_title_content).setVisibility(View.GONE);
            }
            //如果设置了显示ListView
            if (mIsShowListView) {
                ListView listView = new ListView(mContext);
                LinearLayout.LayoutParams listLayoutParams = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
                listView.setLayoutParams(listLayoutParams);
                listView.setAdapter(mAdapter);
                setBottomView(listView);
                if (mItemClickListener != null) {
                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            mItemClickListener.onItemClick(parent, view, position, id);
                            dialog.dismiss();
                        }
                    });
                } else {
                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            dialog.dismiss();
                        }
                    });
                }
            }
            //如果设置了显示底部Negative按钮
            if (mIsShowBottomNegativeButton) {
                if (negativeButton != null) {
                    mDialogLayout.findViewById(R.id.bottom_negative_content).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            negativeButton.onClick(v);
                            dialog.dismiss();
                        }
                    });
                } else {
                    mDialogLayout.findViewById(R.id.bottom_negative_content).setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            dialog.dismiss();
                        }
                    });
                }
            } else {
                mDialogLayout.findViewById(R.id.bottom_negative_content).setVisibility(View.GONE);
            }
            //如果有自定义的动画效果传入,就显示传入的动画效果,否则显示默认效果,另外:传入0,无动画
            if (mIsHaveCustomAnim) {
                if (mCustomAnim != 0) { //设置显示底部dialog的显示动画
                    dialog.getWindow().setWindowAnimations(mCustomAnim);
                }
            } else {                    //设置默认底部dialog的显示动画
                dialog.getWindow().setWindowAnimations(R.style.BottomDialogInAndOutAnim);
            }
            Window dialogWindow = dialog.getWindow();
            dialogWindow.setGravity(Gravity.BOTTOM);
        }


        return dialog;
    }

    public MyDialog setView(View v) {
/*        ((LinearLayout) mDialogLayout.findViewById(R.id.content)).removeAllViews();
        //一定要进行判断,否则第二次弹出Dialog时会报异常
        //异常:java.lang.IllegalStateException: The specified child already has a parent.
        //     You must call removeView() on the child's parent first.
        ViewGroup parent = (ViewGroup) v.getParent();
        if (parent != null) {
            parent.removeAllViews();
        }
        ((LinearLayout) mDialogLayout.findViewById(R.id.content)).addView(v);*/
        ((FrameLayout) mDialogLayout.findViewById(R.id.sv)).removeAllViews();
        ((FrameLayout) mDialogLayout.findViewById(R.id.sv)).addView(v);
        return this;
    }


__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 20 楼 z979451341 的回复:
你的样式第四个和第七个还有bug,我改一下
嗯呐,没有设置颜色,测试List长度了,没改颜色List。确实没有转换异常了。但是高度设置不起作用。。
AlertDialog是怎么设置的呢。。测量List的子项,他测出来的高度是109,- -,我设置的子项算上一条分割线,最高才49
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
你这个数据源mDataArray的元素数量要和mColorArray一样,否则会发生数组越界错误
    //数据源,数组和List
    private String[] mDataArray = {"我是 item 1", "我是 item 2", "我是 item 3", "我是 item 4"};
    private List<String> mDataList = Arrays.asList(mDataArray);

    //颜色值数组和List
    private Integer[] mColorArray = {R.color.blue,R.color.red,R.color.yellow,R.color.green};
    private List<Integer> mColorsList = Arrays.asList(mColorArray);
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
你的样式第四个和第七个还有bug,我改一下
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
ScrollVIew是继承FrameLayout的,所以那个LinearLayout必须要设置FrameLayout类型的LayoutParams
                FrameLayout.LayoutParams LayoutParams = new FrameLayout.LayoutParams(
                        FrameLayout.LayoutParams.MATCH_PARENT,measureListViewWrongHeight(listView));
                ((LinearLayout) mDialogLayout.findViewById(R.id.content)).setLayoutParams(LayoutParams);

                setView(listView);
__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 17 楼 z979451341 的回复:
[quote=引用 16 楼 Lone1yCode 的回复:] [quote=引用 14 楼 z979451341 的回复:] 换这个计算ListView的高度
                    // 动态改变listView的高度  
    public void measureListViewWrongHeight(ListView listView) {  
        ListAdapter listAdapter = listView.getAdapter();  
        if (listAdapter == null) {  
            return;  
        }  
        int totalHeight = 0;  
        for (int i = 0; i < listAdapter.getCount(); i++) {  
            View listItem = listAdapter.getView(i, null, listView);  
            listItem.measure(0, 0);  
            totalHeight += itemHeight;  
        }  
        // 减掉底部分割线的高度  
        int historyHeight = totalHeight  
                + (listView.getDividerHeight() * listAdapter.getCount() - 1);  
        Log.d("Javine","wrongHeight = "+historyHeight); //输出最终ListView的高度  
    }  
0.0 , 这个方法我查资料的时候倒是见过。不过没啥用,并不能解决转换异常。。[/quote] 你现在的代码再上传一次百度云,我下载弄弄[/quote]OK。谢谢大佬。 这是地址:https://pan.baidu.com/s/17M4fXV8xxaVH_VoSlBh6RA 底部弹窗我做了修改,测量ListView的高度,如果高度大于屏幕高度的3/5,就设置list_content的高度为屏幕的3/5,不过好像测量的屏幕高度有问题。有点小。
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
引用 16 楼 Lone1yCode 的回复:
[quote=引用 14 楼 z979451341 的回复:] 换这个计算ListView的高度
                    // 动态改变listView的高度  
    public void measureListViewWrongHeight(ListView listView) {  
        ListAdapter listAdapter = listView.getAdapter();  
        if (listAdapter == null) {  
            return;  
        }  
        int totalHeight = 0;  
        for (int i = 0; i < listAdapter.getCount(); i++) {  
            View listItem = listAdapter.getView(i, null, listView);  
            listItem.measure(0, 0);  
            totalHeight += itemHeight;  
        }  
        // 减掉底部分割线的高度  
        int historyHeight = totalHeight  
                + (listView.getDividerHeight() * listAdapter.getCount() - 1);  
        Log.d("Javine","wrongHeight = "+historyHeight); //输出最终ListView的高度  
    }  
0.0 , 这个方法我查资料的时候倒是见过。不过没啥用,并不能解决转换异常。。[/quote] 你现在的代码再上传一次百度云,我下载弄弄
__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 14 楼 z979451341 的回复:
换这个计算ListView的高度
                    // 动态改变listView的高度  
    public void measureListViewWrongHeight(ListView listView) {  
        ListAdapter listAdapter = listView.getAdapter();  
        if (listAdapter == null) {  
            return;  
        }  
        int totalHeight = 0;  
        for (int i = 0; i < listAdapter.getCount(); i++) {  
            View listItem = listAdapter.getView(i, null, listView);  
            listItem.measure(0, 0);  
            totalHeight += itemHeight;  
        }  
        // 减掉底部分割线的高度  
        int historyHeight = totalHeight  
                + (listView.getDividerHeight() * listAdapter.getCount() - 1);  
        Log.d("Javine","wrongHeight = "+historyHeight); //输出最终ListView的高度  
    }  
0.0 , 这个方法我查资料的时候倒是见过。不过没啥用,并不能解决转换异常。。
x443137254 2018-04-14
  • 打赏
  • 举报
回复
现在到底是什么问题,一会儿讲一样,是dialog的内容如果是listview的话,只显示一行吗
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
换这个计算ListView的高度
                    // 动态改变listView的高度  
    public void measureListViewWrongHeight(ListView listView) {  
        ListAdapter listAdapter = listView.getAdapter();  
        if (listAdapter == null) {  
            return;  
        }  
        int totalHeight = 0;  
        for (int i = 0; i < listAdapter.getCount(); i++) {  
            View listItem = listAdapter.getView(i, null, listView);  
            listItem.measure(0, 0);  
            totalHeight += itemHeight;  
        }  
        // 减掉底部分割线的高度  
        int historyHeight = totalHeight  
                + (listView.getDividerHeight() * listAdapter.getCount() - 1);  
        Log.d("Javine","wrongHeight = "+historyHeight); //输出最终ListView的高度  
    }  
__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 12 楼 z979451341 的回复:
不过你可以换条思路,通过计算ListView长度来设置这个LinearLayout长度
嗯呐,我试过这个方法,测量ListView的高度来设置content的高度,但是设置后,运行就会出现转换异常,我不是很明白这个是怎么回事。
在设置替换List之前,先测量一下List,把高度给content:

然后就会出现这个问题:

键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
不过你可以换条思路,通过计算ListView长度来设置这个LinearLayout长度
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
引用 10 楼 Lone1yCode 的回复:
引用 9 楼 z979451341 的回复:
改变R.id.content的LinearLayout的android:layout_height="400dp"
不能自动适应吗。固定高度没有作用,设置minHeight倒是可以,不过内容是文本且只有一行的时候,高度就太大了。List显示的内容就会显示不完整。
不能,子View的大小由父ViewGroup的LayoutParams决定,你的子View虽然是match_parent,但是你的父ViewGroup是wrap_content,基本只计算最小情况
__椎名真白 2018-04-14
  • 打赏
  • 举报
回复
引用 9 楼 z979451341 的回复:
改变R.id.content的LinearLayout的android:layout_height="400dp"
不能自动适应吗。固定高度没有作用,设置minHeight倒是可以,不过内容是文本且只有一行的时候,高度就太大了。List显示的内容就会显示不完整。
键盘舞者113 2018-04-14
  • 打赏
  • 举报
回复
改变R.id.content的LinearLayout的android:layout_height="400dp"
加载更多回复(5)
丰富的工具类框架 包含常用的工具类方便快速开发 持续更新中 可直接使用implementation 引入使用 2018.9.17 工具类集合 MLog工具类 日期获取工具类 网络检查工具类 权限检查工具类 MD5工具类 日志保存工具类 SheetDialog 底部弹出框 LogcatHelper.getInstance(this).start(filePath); 开启保存日志 LogcatHelper.getInstance(this).stop(); 停止保存日志 2018.9.18 添加检查工具类 图片工具类 屏幕工具类 存储工具类 正则校验工具类 String工具类 Toast工具类 自定义圆形imageView (CircleImageView) 自定义loadingDialog 自定义带旋转动画的loadingDialog 2018.10.27 修改Toast工具类 添加可以在服务中进行提示的toast 添加设备信息工具类 添加时间管理工具类 2018.11.13 修改屏幕工具类 添加dpi px sp 等转换方法 添加button防多点工具类 添加文件读写工具类 添加glide网络图片加载工具类 添加wifi操作工具类 2018.1.3 丰富了手机工具类的方法集 添加蓝牙工具类方法集、蓝牙扫描回调接口 wifi工具类添加连接指令wifi方法 2018.1.9 修复一些方法调用方式 手机工具类添加手机电量监听,添加获取本机开发这模式开关 添加测试工程 蓝牙工具类添加蓝牙工具类方法 wifi工具类优化wifi工具类扫描结果 2018.1.25 添加下载模块 支持断点下载,多任务下载 删除下载 添加下载模块测试用例 2018.2.20 优化工具类调用 wifi工具类和蓝牙工具类优化 实现单例 添加打字机效果 2018.2.20 修改bug 手机工具类添加获取运行内存 cpu型号 电池容量等方法 wifi工具类添加注册监听wifi状态和连接状态监听回调 2018.3.20 添加蓝牙连接状态监听,添加开关蓝牙接口 2018.3.29 wifi工具类添加密码错误监听 手机工具类添加电量监听 运行内存修复 蓝牙工具类添加蓝牙扫描监听和取消 时间工具类修复倒计时方法 添加停止倒计时方法 2018.4.3 添加检查权限回调 单例时间管理类

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧