带有圆角而不是 100% 屏幕宽度的自定义片段对话框
Posted
技术标签:
【中文标题】带有圆角而不是 100% 屏幕宽度的自定义片段对话框【英文标题】:Custom FragmentDialog with round corners and not 100% screen width 【发布时间】:2013-03-03 12:14:50 【问题描述】:我正在创建一个带有圆角的自定义片段对话框,其布局不会填满屏幕宽度(我希望它只是包装其内容)。
这是我在可绘制文件夹中的rounded_dialog.xml
,我的自定义ThemeWithCorners
调用它作为对话框的背景。我还尝试将其设置为创建其内容的线性布局的背景,但没有任何效果。
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<solid android:color="@android:color/white"/>
<corners android:radius="20dp"
/>
</shape>
这就是我调用对话框的方式:
final String FTAG = "TAG_FRAGMENT_DIALOG_CALENDAR";
dialog = (CalendarDialog) fm.findFragmentByTag(FTAG);
ft = fm.beginTransaction();
if (dialog != null)
ft.remove(dialog);
dialog = CalendarDialog.newInstance(this);
dialog.setCancelable(true);
ft.add(dialog, FTAG);
ft.show(dialog);
ft.commit();
在对话框的 onCreate 方法中,我设置了样式和主题:
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_TITLE, R.style.ThemeWithCorners);
这是 onCreateView 方法:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
getDialog().setCanceledOnTouchOutside(true);
v = (MyCalendar)inflater.inflate(R.layout.calendar_dialog, container, true)
return v;
我还尝试将其添加到 onCreateDialog 方法中,作为 SO 建议的其他答案,但也没有工作:
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
Dialog d = super.onCreateDialog(savedInstanceState);
LayoutParams lp=d.getWindow().getAttributes();
d.getWindow().setBackgroundDrawable(new ColorDrawable(0));
lp.width=-2;lp.height=-2;lp.gravity=Gravity.CENTER;
lp.dimAmount=0;
lp.flags=LayoutParams.FLAG_LAYOUT_NO_LIMITS | LayoutParams.FLAG_NOT_TOUCH_MODAL;
return d;
所以总结一下,我想要圆角,而不是 100% 的屏幕宽度,它最好应该包裹它的内容。拜托,拜托,我需要一些帮助,我真的很绝望,我已经尝试了好几天了!
【问题讨论】:
【参考方案1】:好吧,我刚刚找到了一个解决方案,但我对此并不满意。
我这样设置对话框的背景(rounded_dialog.xml):
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent"/>
<corners android:radius="10dp" />
<padding android:left="10dp" android:right="10dp"/>
</shape>
然后我在下面的“onCreateView”方法中将它设置为我的对话框。圆角在这段代码中并不是必须的,因为背景是透明的,但是 padding 很重要,因为对话框实际上仍然和屏幕一样宽,但是 padding 使它看起来不像。
getDialog().getWindow().setBackgroundDrawableResource(R.drawable.rounded_dialog);
最后,我将对话框组件的背景设置为另一个自定义可绘制对象,使角落变圆。我有一个 LinearLayout,顶部是 RelativeLayout,底部是 TextView,所以我将 @null 设置为父 LinearLayout 并为这两个部分设置两个不同的自定义可绘制对象,其中一个具有圆角底部角,另一个具有顶部角。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical"
android:background="@drawable/title_round"
>
<RelativeLayout
android:id="@+id/title"
android:layout_
android:layout_
android:orientation="horizontal"
android:background="@drawable/blue_title_round_top"
android:paddingTop="4dp"
android:paddingBottom="4dp"
>
<TextView
android:id="@+id/calendarHint"
android:layout_
android:layout_
android:background="@drawable/rounded_bottom"
android:layout_gravity="center"
android:gravity="center"
/>
</LinearLayout>
我相信有一个更合适的解决方案,因为这在视觉上是正确的,而不是真正的功能,但对于这种情况来说足够正确。
【讨论】:
【参考方案2】:对话背景: dialog_rounded_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="12dp" />
</shape>
对话框布局: dialog_rounded.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:background="@drawable/dialog_rounded_bg"
android:minWidth="260dp"
android:orientation="vertical"
android:padding="24dp">
...
</LinearLayout>
对话片段: RoundedDialog.java
public class RoundedDialog extends DialogFragment
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
View view = inflater.inflate(R.layout.dialog_rounded, container, false);
// Set transparent background and no title
if (getDialog() != null && getDialog().getWindow() != null)
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
return view;
...
更新:如果您不设置标志 Window.FEATURE_NO_TITLE
,则在 Android ≤ 4.4 的设备的对话框顶部设置 blue line appears。
【讨论】:
你在对话框中使用了什么字体? 这是一种自定义字体(Maison Neue)。 此解决方案也适用于ConstraintLayout
而不是 LinearLayout
。【参考方案3】:
另一种方式:
在onCreate()
方法中使用setStyle()
将样式应用 到您的DialogFragment
。然后,您可以像往常一样在根视图 中使用android:background
> 的your_layout.xml
文件。
步骤:
-
style.xml 文件(在 res 文件夹中):
<style name="DialogTheme_transparent" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<!--You can set other style items also, such as animations and etc-->
</style>
-
在布局文件夹中创建
your_layout.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_
android:padding="8dp"
android:background="@drawable/bg_corner_dialog">
...
</LinearLayout>
-
在drawable文件夹中创建
bg_corner_dialog.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:dither="true">
<solid android:color="#ffffff"/>
<corners android:radius="16dp"/>
</shape>
-
最后将
style
和layout
应用到你的DialogFragment
:
public class CustomDialogFragment extends DialogFragment
...
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setStyle(STYLE_NO_TITLE, R.style.DialogTheme_transparent);
...
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
View v = inflater.inflate(R.layout.your_layout, container, false);
ButterKnife.bind(this, v);
//init UI Elements...
return v;
希望对您有所帮助。 最好的祝福
【讨论】:
【参考方案4】:我认为制作圆角,如果您将 cardview 作为布局的根并在 onCreateView() 中添加以下代码,会容易得多: alertDialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent)
【讨论】:
它对我不起作用,对显示的对话框没有影响【参考方案5】:使用 Kotlin 和视图绑定更新了 2022 年的答案 -
class InternetLostDialog : DialogFragment()
private lateinit var binding: DialogInternetLostBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog
binding = DialogInternetLostBinding.inflate(LayoutInflater.from(context))
val builder = AlertDialog.Builder(requireActivity())
isCancelable = false
builder.setView(binding.root)
binding.root.setOnClickListener
requireActivity().finish()
val dialog = builder.create()
dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
return dialog
【讨论】:
【参考方案6】:适用于我使用 Kotlin 的更新解决方案。
我这样设置对话框的背景(rounded_dialog.xml):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="@color/white"/>
</shape>
然后以编程方式计算屏幕宽度,然后从中减去 Margin 值,使用此代码 sn-p。
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
val width = displayMetrics.widthPixels
然后在 onStart 回调中,我应用了该宽度减去边距。 这是完整的代码。
@AndroidEntryPoint
class CancelDialogFragment : DialogFragment()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View?
if (dialog != null && dialog?.window != null)
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE);
return inflater.inflate(R.layout.fragment_cancel_dialog, container, false)
override fun onStart()
super.onStart()
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
val width = displayMetrics.widthPixels
val height = displayMetrics.heightPixels
dialog?.window?.setLayout(width-64, ViewGroup.LayoutParams.WRAP_CONTENT)
XML 布局fragment_cancel_dialog
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:paddingVertical="32dp"
android:padding="8dp"
android:layout_marginHorizontal="8dp"
android:background="@drawable/rounded_dialog"
tools:context=".ui.orders.CancelDialogFragment">
<TextView
android:id="@+id/textView9"
android:layout_
android:layout_
android:layout_marginTop="16dp"
android:text="Reason of cancellation"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="@+id/firstNameTIL"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/firstNameTIL"
android:layout_
android:layout_
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
app:hintAnimationEnabled="false"
app:hintEnabled="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView9">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/firstNameET"
android:layout_
android:layout_
android:background="@drawable/edit_text_bg"
android:drawablePadding="12dp"
android:inputType="textPersonName"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
android:textAlignment="viewStart"
android:textColor="@color/textColor"
android:textColorHint="@color/black" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/signUpButton"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:background="@drawable/button_bg"
android:paddingHorizontal="56dp"
android:text="@string/confirmStr"
android:textAllCaps="false"
android:inputType="text"
android:textColor="@color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/firstNameTIL" />
</androidx.constraintlayout.widget.ConstraintLayout>
【讨论】:
【参考方案7】:对于任何想要使用 AlertDialogBuilder 并透明背景并在 XML 文件中设置 Drawable 的人。
<style name="DialogStyle" parent="ThemeOverlay.MaterialComponents.Dialog.Alert">
<item name="android:background">@drawable/dialog_background</item>
<item name="android:windowBackground">@android:color/transparent</item>
在 Builder 上设置这个主题,如下所示
private val builder: AlertDialog.Builder = AlertDialog.Builder(context,R.style.DialogStyle)
.setView(dialogView)
R.drawable.dialog_background 在哪里
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" android:padding="10dp">
<solid
android:color="@color/dialog_bg_color"/>
<corners
android:radius="30dp" />
</shape>
</item>
【讨论】:
以上是关于带有圆角而不是 100% 屏幕宽度的自定义片段对话框的主要内容,如果未能解决你的问题,请参考以下文章