android 上的 AlertDialog 内 EditText 扩展太慢
EditText expands too slow inside AlertDialog on android
简化更复杂的问题。
我有一个带有此视图的 AlertDialog dialog.xml(我可能错了,这个问题与 AlertDialog 无关,但与一般视图无关):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
// <ImageView 48dp x 48dp/> ImageView for profile photo
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:maxLines="5"
android:inputType="textMultiLine"
android:scrollbars="vertical"
android:scrollHorizontally="false"/>
// <ImageView 48dp x 48dp> ImageView for a send button.
</LinearLayout>
我需要将整个对话框放在底部,就在键盘上方,这样它就类似于聊天程序。我需要它作为浮动对话框,因为它没有绑定到父视图中的任何一个地方。
我这样做(在客户端代码中)是为了实现:
dialog.show(); // above dialog
Window window dialog.getWindow();
window.setGravity(Gravity.BOTTOM);
window.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
现在,当我键入时,编辑字段正确地扩展到最多 5 行(从下到上)。但是如果我打字太快(按回车键快速创建新行),对话框展开动画(高度向下增加)比对话框向上移动动画慢。这会导致对话框出现 1-2 秒漂浮在空中,其下边框和键盘之间有一个小间隙。
我怎样才能防止这种情况(消除中间的 space)?或者让动画耗时 0 秒?
澄清一下:我不需要为对话框禁用动画 popup/dismiss。当 window 扩展太快时(例如通过创建新行),window 会向上移动,而高度不能足够快地补偿移动,留下一个小的临时(1-2 秒)间隙在对话框和键盘之间。这可能是一般浮动视图的基本问题(我尝试使用具有相同效果的 PopupWindow)。
对话与差距:
1-2 秒后变成这样(当展开动画终于赶上时):
要删除动画,请按照以下步骤操作:
在/res/anim的基础上增加了一个no_anim.xml,关键是设置duration为0
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="0" />
使用 0 持续时间动画定义自定义样式:
<style name="NoAnimation">
<item name="android:windowEnterAnimation">@anim/no_anim</item>
<item name="android:windowExitAnimation">@anim/no_anim</item>
</style>
- 将样式应用于您的 AlertDialog:
dialog.getWindow().getAttributes().windowAnimations = R.style.NoAnimation;
在对堆栈溢出答案进行大量挖掘后没有结果后,我自己找到了解决方案。
想法是首先将整个对话框展开为全屏,但有一个覆盖空白部分的透明覆盖视图。
dialog.xml 现在看起来像这样:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Transparent view that extends over entire screen and push comment view to the bottom -->
<View
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/transparent"/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/white"
android:orientation="horizontal">
// <ImageView 48dp x 48dp/> ImageView for profile photo
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:maxLines="5"
android:inputType="textMultiLine"
android:scrollbars="vertical"
android:scrollHorizontally="false"/>
// <ImageView 48dp x 48dp> ImageView for a send button.
</LinearLayout>
</LinearLayout>
Java代码:
public void showDialog() {
View content = activity.getLayoutInflater().inflate(R.layout.dialog, null, false);
// This makes top LinearLayout background transparent, without this,
// it will be all white covering fullscreen.
content.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Dialog dialog = new AlertDialog.Builder(context)
.setView(content).create();
dialog.show(); // needs to be done before window changes
Window window dialog.getWindow();
window.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
View overlay = content.findViewById(R.id.overlay);
overlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (dialog.isShowing()) {
dialog.cancel();
}
}
});
}
简化更复杂的问题。
我有一个带有此视图的 AlertDialog dialog.xml(我可能错了,这个问题与 AlertDialog 无关,但与一般视图无关):
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
// <ImageView 48dp x 48dp/> ImageView for profile photo
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:maxLines="5"
android:inputType="textMultiLine"
android:scrollbars="vertical"
android:scrollHorizontally="false"/>
// <ImageView 48dp x 48dp> ImageView for a send button.
</LinearLayout>
我需要将整个对话框放在底部,就在键盘上方,这样它就类似于聊天程序。我需要它作为浮动对话框,因为它没有绑定到父视图中的任何一个地方。
我这样做(在客户端代码中)是为了实现:
dialog.show(); // above dialog
Window window dialog.getWindow();
window.setGravity(Gravity.BOTTOM);
window.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
现在,当我键入时,编辑字段正确地扩展到最多 5 行(从下到上)。但是如果我打字太快(按回车键快速创建新行),对话框展开动画(高度向下增加)比对话框向上移动动画慢。这会导致对话框出现 1-2 秒漂浮在空中,其下边框和键盘之间有一个小间隙。
我怎样才能防止这种情况(消除中间的 space)?或者让动画耗时 0 秒?
澄清一下:我不需要为对话框禁用动画 popup/dismiss。当 window 扩展太快时(例如通过创建新行),window 会向上移动,而高度不能足够快地补偿移动,留下一个小的临时(1-2 秒)间隙在对话框和键盘之间。这可能是一般浮动视图的基本问题(我尝试使用具有相同效果的 PopupWindow)。
对话与差距:
1-2 秒后变成这样(当展开动画终于赶上时):
要删除动画,请按照以下步骤操作:
在/res/anim的基础上增加了一个no_anim.xml,关键是设置duration为0
<scale xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%" android:duration="0" />
使用 0 持续时间动画定义自定义样式:
<style name="NoAnimation"> <item name="android:windowEnterAnimation">@anim/no_anim</item> <item name="android:windowExitAnimation">@anim/no_anim</item> </style>
- 将样式应用于您的 AlertDialog:
dialog.getWindow().getAttributes().windowAnimations = R.style.NoAnimation;
在对堆栈溢出答案进行大量挖掘后没有结果后,我自己找到了解决方案。
想法是首先将整个对话框展开为全屏,但有一个覆盖空白部分的透明覆盖视图。
dialog.xml 现在看起来像这样:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Transparent view that extends over entire screen and push comment view to the bottom -->
<View
android:id="@+id/overlay"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/transparent"/>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/white"
android:orientation="horizontal">
// <ImageView 48dp x 48dp/> ImageView for profile photo
<EditText
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:maxLines="5"
android:inputType="textMultiLine"
android:scrollbars="vertical"
android:scrollHorizontally="false"/>
// <ImageView 48dp x 48dp> ImageView for a send button.
</LinearLayout>
</LinearLayout>
Java代码:
public void showDialog() {
View content = activity.getLayoutInflater().inflate(R.layout.dialog, null, false);
// This makes top LinearLayout background transparent, without this,
// it will be all white covering fullscreen.
content.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Dialog dialog = new AlertDialog.Builder(context)
.setView(content).create();
dialog.show(); // needs to be done before window changes
Window window dialog.getWindow();
window.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
View overlay = content.findViewById(R.id.overlay);
overlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (dialog.isShowing()) {
dialog.cancel();
}
}
});
}