B T*_*B T 56 java android android-layout android-alertdialog android-dialogfragment
我在我正在构建的应用程序中遇到此问题.请忽略所有设计缺点和缺乏最佳实践方法,这纯粹是为了展示我无法解决的一个例子.
我有DialogFragment一个AlertDialog使用自定义View设置返回基本AlertDialog.Builder.setView().如果这View有特定的大小要求,我如何Dialog正确调整自身大小以显示自定义中的所有内容View?
这是我一直使用的示例代码:
package com.test.test;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Use a button for launching
Button b = new Button(this);
b.setText("Launch");
b.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Launch the dialog
myDialog d = new myDialog();
d.show(getFragmentManager(), null);
}
});
setContentView(b);
}
public static class myDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Create the dialog
AlertDialog.Builder db = new AlertDialog.Builder(getActivity());
db.setTitle("Test Alert Dialog:");
db.setView(new myView(getActivity()));
return db.create();
}
protected class myView extends View {
Paint p = null;
public myView(Context ct) {
super(ct);
// Setup paint for the drawing
p = new Paint();
p.setColor(Color.MAGENTA);
p.setStyle(Style.STROKE);
p.setStrokeWidth(10);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(800, 300);
}
@Override
protected void onDraw(Canvas canvas) {
// Draw a rectangle showing the bounds of the view
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), p);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Button创建A ,打开DialogFragment单击.custom View(myView)的宽度必须为800,高度为300,并且在覆盖范围内正确设置onMeasure().这View,绘制其测量界限洋红色进行调试.
800宽度比Dialog我的设备上的默认大小宽,但被剪裁而不是正确拉伸.
我查看了以下解决方案:
我推导出以下两种编码方法:
WindowManager.LayoutParams的Dialog,并用它们覆盖myDialog.getDialog().getWindow().get/setAttributes()setLayout(w, h)方法通过myDialog.getDialog().getWindow().setLayout()我曾尝试他们无处不在,我能想到的(压倒一切onStart(),在onShowListener之后的Dialog创建和显示等),一般都可以得到,如果这两种方法能够正常工作LayoutParams是提供一个特定的值.但无论何时WRAP_CONTENT提供,都没有任何反应.
有什么建议?
编辑:
情况截图:

特定值的屏幕截图(在这里输入注释900,850没有覆盖视图的整个宽度,这在整个窗口正在调整的情况下是有意义的.因此,如果需要另一个,则提供 - 为什么WRAP_CONTENT必要/固定的原因值不合适):

B T*_*B T 61
我有一个工作的解决方案,说实话,我认为挖掘方式太深,无法获得如此简单的结果.但这里是:
究竟发生了什么:
通过Dialog使用Hierarchy Viewer打开布局,我能够检查整个布局AlertDialog以及究竟发生了什么:

的蓝色亮点是所有的高电平部分的(Window,帧的Dialog视觉风格等),并从所述的端部蓝色向下是,其中用于所述部件AlertDialog顷(红色 =标题,黄色 =一个滚动视图存根,也许对列表AlertDialog小号,绿色 = Dialog内容即自定义视图,橙色 =按钮).
从这里可以清楚地看到,7视图路径(从蓝色开始到绿色结束)是未正确的WRAP_CONTENT.看着LayoutParams.width每一个都View透露了所有的东西都被给定了LayoutParams.width = MATCH_PARENT(我猜在顶部)一个大小被设定.因此,如果您遵循该树,很明显您View在树底部的自定义将永远无法影响该树的大小Dialog.
那么现有的解决方案在做什么呢?
View并修改它LayoutParams.显然,View树中的所有对象都与父级匹配,如果顶级设置为静态大小,则整体Dialog将改变大小.但是如果顶级设置为WRAP_CONTENT,View则树中的所有其他对象仍然在查找树以"匹配他们的父母",而不是向下看树以"包裹它们的内容".如何解决问题:
坦率地说,改变影响路径中LayoutParams.width的所有View对象WRAP_CONTENT.
我发现这只能在调用onStart生命周期步骤之后完成DialogFragment.所以onStart实现如下:
@Override
public void onStart() {
// This MUST be called first! Otherwise the view tweaking will not be present in the displayed Dialog (most likely overriden)
super.onStart();
forceWrapContent(myCustomView);
}
Run Code Online (Sandbox Code Playgroud)
然后是适当修改View层次结构的函数LayoutParams:
protected void forceWrapContent(View v) {
// Start with the provided view
View current = v;
// Travel up the tree until fail, modifying the LayoutParams
do {
// Get the parent
ViewParent parent = current.getParent();
// Check if the parent exists
if (parent != null) {
// Get the view
try {
current = (View) parent;
} catch (ClassCastException e) {
// This will happen when at the top view, it cannot be cast to a View
break;
}
// Modify the layout
current.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
}
} while (current.getParent() != null);
// Request a layout to be re-done
current.requestLayout();
}
Run Code Online (Sandbox Code Playgroud)
以下是工作结果:

它让我感到困惑的是为什么整个Dialog人不希望WRAP_CONTENT用一个明确的minWidth集合来处理所有符合默认大小的情况,但我确信它有一个很好的理由(它会有兴趣听到它) .
swe*_*sen 33
后
dialog.show();
Run Code Online (Sandbox Code Playgroud)
只是用
dialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, yourHeight);
Run Code Online (Sandbox Code Playgroud)
非常简单的解决方案,但它适用于我.我正在扩展一个对话框但是假设这也适用于DialogFragment.
Sim*_*mon 12
AlertDialog使用这两个窗口属性来定义它们的最小尺寸,以便在平板电脑上它们以合理的宽度浮动在屏幕的中心.
http://developer.android.com/reference/android/R.attr.html#windowMinWidthMajor http://developer.android.com/reference/android/R.attr.html#windowMinWidthMinor
您可以扩展所选的默认对话框样式,并更改值以应用您自己的逻辑.
这对我来说没问题:
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(dialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
dialog.show();
dialog.getWindow().setAttributes(lp);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
48811 次 |
| 最近记录: |