[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会只显示一行,虽然可以滑动;替换布局不再生效。
怎么改才合适呢?期望效果是内容过长时,内容区可滑动,底部按钮一定要显示
就像默认的对话框效果一样:


求助攻。。。

...全文
1202 25 打赏 收藏 转发到动态 举报
AI 作业
写回复
用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)

80,471

社区成员

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

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