Android自定义AlertDialog及设置宽高无效问题

本篇记录自定义AlertDialog以及遇到的问题

自定义AlertDialog

先上效果图
在这里插入图片描述

创建布局

首先我们要创建想要的dialog布局文件

<?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="200dp"
    android:background="@drawable/style_linearlayout_round_bg"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <TextView
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:text="@string/penaltyType"
            android:gravity="center"
            android:textColor="@color/colorAccent" />
        <Spinner
            android:id="@+id/sp_penalty"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:entries="@array/penaltyArray" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <TextView
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:text="@string/penaltyContent"
            android:gravity="center"
            android:textColor="@color/colorAccent" />
        <EditText
            android:id="@+id/et_penaltyContent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:inputType="text" />
    </LinearLayout>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:background="@color/gray" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:gravity="center">
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.6"
            android:visibility="invisible" />
        <Button
            android:id="@+id/btn_save"
            android:layout_width="wrap_content"
            android:layout_height="32dp"
            android:background="@drawable/style_button_round_bg"
            android:textColor="@color/white"
            android:text="@string/save" />
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.8"
            android:visibility="invisible" />
        <Button
            android:id="@+id/btn_close"
            android:layout_width="wrap_content"
            android:layout_height="32dp"
            android:background="@drawable/style_button_round_bg"
            android:textColor="@color/white"
            android:text="@string/close" />
        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.6"
            android:visibility="invisible" />
    </LinearLayout>

</LinearLayout>

我们要把AlertDialog做成这个样子,然后创建好自定义布局之后,就要在Activity/Fragment中进行操作了。

添加布局

在Activity中把创建好的布局添加到我们的AlertDialog中,就可以了。

        View customPenaltyView = LayoutInflater.from(mContext).inflate(R.layout.widget_custom_select_penalty, null, false);
        ......
        
        // 设置自定义布局
        dialog.setView(customPenaltyView);
        // 也可以通过这种方式设置布局
        Objects.requireNonNull(dialog.getWindow()).setContentView(customPenaltyView);

这儿之所以会有两种方式,是因为网上有些自定义Dialog会在使用第一种方式设置布局的时候,把布局填充到了Dialog的Title和Button之间的区域,这种情况下,使用第二中方式可以解决。(Ps:还没有遇到过),一般情况下,都是使用第一种方式。

增加监听

布局设置好之后,就对布局上的控件做一些监听处理基本上就可以了。

        final AlertDialog dialog = new AlertDialog.Builder(mContext).create();
        final Spinner penaltyType = customPenaltyView.findViewById(R.id.sp_penalty);
        final EditText penaltyContent = customPenaltyView.findViewById(R.id.et_penaltyContent);
        final String [] penaltyTypeArray = getResources().getStringArray(R.array.penaltyArray);
        final String[] penaltyTypeString = new String[1];
        dialog.setView(customPenaltyView);
        Button save  = customPenaltyView.findViewById(R.id.btn_save);
        Button close  = customPenaltyView.findViewById(R.id.btn_close);
        penaltyType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    
    
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    
    
                penaltyTypeString[0] = penaltyTypeArray[position];
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
    
    

            }
        });
        save.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                dialog.dismiss();
                Toast.makeText(mContext, penaltyTypeString[0] + penaltyContent.getText().toString(), Toast.LENGTH_SHORT).show();
            }
        });
        close.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                dialog.dismiss();
            }
        });
        dialog.show();
        Objects.requireNonNull(dialog.getWindow()).setBackgroundDrawableResource(R.color.transparent);

总结

有了上面的三步,基本上就可以把AlertDIalog做成想要的样子。

也可以简洁一点,这样做。

		// 自定义的布局
		View addPlayerView = LayoutInflater.from(mContext).inflate(R.layout.widget_custom_alertdialog_addplayer, null, false);
		// 把布局添加到dialog
        final AlertDialog dialog = new AlertDialog.Builder(mContext, R.style.AlertDialog_AppCompat_Transparent).setView(addPlayerView).create();
        // 监听
        final EditText addPlayerName = addPlayerView.findViewById(R.id.et_addPlayerName);
        TextView addPlayerData = addPlayerView.findViewById(R.id.tv_addPlayerButton);
        addPlayerData.setOnClickListener(new View.OnClickListener() {
    
    
            @Override
            public void onClick(View v) {
    
    
                dialog.dismiss();
                Toast.makeText(TruthOrDareActivity.this, "添加玩家" + addPlayerName.getText().toString(), Toast.LENGTH_SHORT).show();
            }
        });
        dialog.show();

最后就是遇到的问题

  1. 布局填充区域不对

在添加布局中,把布局文件填充到Dialog的一部分区域中,可以通过Dialog的getWindow的setContentView方法来设置,可以看上面的第二步,添加布局。

  1. 设置宽高失效

在布局文件中设置宽高失效的问题,依然可以在Window中设置相关属性来实现。我们可以获取屏幕高宽,然后设置想要的位置。

  1. 布局文件要用相对布局

布局文件使用RelativeLayout,如果使用线性布局LinearLayout会导致自定义xml的大小(宽高)无法调节

  1. RelativeLayout设置高度无效的问题

在使用相对布局设置高度时,高度无效的问题,其实并不是layout_height无效,而是它根据子控件里,最大的控件高度来设置的。
意味着:在最外层的RelativeLayout中设置高度为match_parent或者具体的高度,如果子控件设置了高度是match_parent,且子控件的高度小于最外层的最大高度时,就会出现失效的情况。其实,并没有失效,而是他根据子控件中的最大高度来设置的。就相当于wrap_parent。
参考:
自定义Dialog
自定义Dialog宽高无效

猜你喜欢

转载自blog.csdn.net/A_Intelligence/article/details/109956097