在实施 StrikeForceZero 和 Luke Sleeman 建议的解决方案时遇到了一些麻烦,所以我想贡献我的经验。我敢肯定,我只是缺少一些东西,因此非常感谢您的反馈。
我所做的是以下内容:
使用提供的 PopupTheme 创建样式,直接复制/粘贴:
<style name="PopupTheme" parent="android:Theme.Holo.Light.Dialog">
<item name="android:windowIsFloating">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowIsTranslucent">true</item>
</style>
添加 showAsPopup() 方法作为片段中的方法,该方法将打开假对话片段,直接复制/粘贴:
private void showAsPopup(Activity activity) {
//To show activity as dialog and dim the background, you need to declare android:theme="@style/PopupTheme" on for the chosen activity on the manifest
activity.requestWindowFeature(Window.FEATURE_ACTION_BAR);
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
LayoutParams params = activity.getWindow().getAttributes();
params.alpha = 1.0f;
params.dimAmount = 0f;
activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
// This sets the window size, while working around the IllegalStateException thrown by ActionBarView
activity.getWindow().setLayout(850,850);
}
使用简单的 new() 调用创建新活动的实例,然后将其传递给 showAsPopup() 方法:
DialogTestActivity test = new DialogTestActivity();
showAsPopup(test);
为了测试的目的(我只是想确认我可以打开一个显示为带有操作栏的对话框的活动)我使用了一个非常简单的测试,直接从按钮视图 api 演示中窃取(用于布局文件,请参阅 api 演示中的buttons_1.xml):
public class DialogTestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.buttons_test);
}
}
不幸的是,每次我尝试这个时,我都会在第一次调用时得到一个未指定的空指针异常,activity.requestWindowFeature(Window.FEATURE_ACTION_BAR);
04-29 16:39:05.361: W/System.err(15134): java.lang.NullPointerException
04-29 16:39:05.361: W/System.err(15134): at android.app.Activity.requestWindowFeature(Activity.java:3244)
04-29 16:39:05.371: W/System.err(15134): at packagenameremovedforlegalreasons.classname.showAsPopup(classname.java:602)
04-29 16:39:05.371: W/System.err(15134): at packagenameremovedforlegalreasons.classname.onMapLongClick(classname.java:595)
04-29 16:39:05.371: W/System.err(15134): at com.google.android.gms.maps.GoogleMap$5.onMapLongClick(Unknown Source)
04-29 16:39:05.371: W/System.err(15134): at com.google.android.gms.internal.k$a.onTransact(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at android.os.Binder.transact(Binder.java:310)
04-29 16:39:05.381: W/System.err(15134): at com.google.android.gms.maps.internal.IOnMapLongClickListener$Stub$Proxy.onMapLongClick(IOnMapLongClickListener.java:93)
04-29 16:39:05.381: W/System.err(15134): at maps.i.s.a(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at maps.y.v.d(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at maps.y.bf.onLongPress(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at maps.d.v.onLongPress(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at maps.d.h.c(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at maps.d.h.c(Unknown Source)
04-29 16:39:05.381: W/System.err(15134): at maps.d.j.handleMessage(Unknown Source)
04-29 16:39:05.391: W/System.err(15134): at android.os.Handler.dispatchMessage(Handler.java:99)
04-29 16:39:05.391: W/System.err(15134): at android.os.Looper.loop(Looper.java:137)
04-29 16:39:05.391: W/System.err(15134): at android.app.ActivityThread.main(ActivityThread.java:5041)
04-29 16:39:05.391: W/System.err(15134): at java.lang.reflect.Method.invokeNative(Native Method)
04-29 16:39:05.391: W/System.err(15134): at java.lang.reflect.Method.invoke(Method.java:511)
04-29 16:39:05.391: W/System.err(15134): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-29 16:39:05.391: W/System.err(15134): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-29 16:39:05.391: W/System.err(15134): at dalvik.system.NativeStart.main(Native Method)
正如您从堆栈跟踪中看到的那样,预期的行为是在 GoogleMap 实例上长按打开窗口(使用 API 2 中的 MapFragments)。所以我的第一个想法是尝试从 Fragment 打开存在问题,所以我将调用传递回拥有的 Activity。同样的错误,同样没有附加信息。
在这一点上,我最好的猜测是 new() 调用没有充分实例化类/视图以进行调用以修改其视图。事实证明,这似乎至少在某种程度上是正确的,因为将视图修改代码迁移到活动中并以正常方式简单地打开活动是可行的:
调用活动:
public void openMapDialog()
{
Intent intent = new Intent(this, DialogTestActivity.class);
startActivity(intent);
}
新班级代码:
public class DialogTestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// From: https://stackoverflow.com/questions/11425020/actionbar-in-a-dialogfragment
this.requestWindowFeature(Window.FEATURE_ACTION_BAR);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND, WindowManager.LayoutParams.FLAG_DIM_BEHIND);
LayoutParams params = this.getWindow().getAttributes();
params.alpha = 1.0f;
params.dimAmount = 0f;
this.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
// This sets the window size, while working around the IllegalStateException thrown by ActionBarView
this.getWindow().setLayout(600,600);
setContentView(R.layout.buttons_test);
}
}
所以我想我发布所有这些的目的是为了澄清如果你想做上述海报建议的事情,你不能只是 new() 一个活动并调用 showAsPopup()。这可能是我对 Android 显示的缺乏经验,但是虽然这似乎有点明显,但将 showAsPopup() 解释为由当前视图调用而不是正在创建的视图调用似乎也很自然,因为您正在传递活动实例(如果它应该在 onCreate() 中完成,就像我最终做的那样)。
因此,如果意图是在创建活动而不是创建活动中调用 showAsPopup(),那么在调用 onCreate() 之前如何获取可修改的 Activity 实例并不明显。问题是您不能在调用 setContentView() 之后调用诸如 requestWindowFeature() 之类的东西(示例),这是一个问题,因为它通常在 onCreate() 中调用。
同样,如果有一种简单/更好的方法可以做到这一点,我将非常感谢反馈。希望这对想要使用这种方法的人有所帮助。