ActionBar в диалоговом окне диалога
В приложении "Календарь" на моей вкладке Galaxy Tab 10.1 при создании нового события в диалоговом окне появляются кнопки "Готово" и "Отмена" в области заголовка/панели действий.
![enter image description here]()
Я хотел бы реализовать это в своем приложении. Я попытался использовать setHasOptionsMenu(true)
в дополнение к переопределению onCreateOptionsMenu
в моем подклассе DialogFragment
, но мои элементы действия не отображаются. Я также пробовал вызывать getDialog().getActionBar()
из onCreateView
, но всегда возвращает null
.
Я могу получить эту работу, если я начинаю Activity
, а не показывая диалог, но это занимает весь экран. Есть ли стандартный способ сделать это, используя DialogFragment
?
Ответы
Ответ 1
используя идею из сообщение google group, я смог снять его с создания стиля. вы хотели бы изменить высоту и ширину до "динамического" размера по вашему выбору. Затем установите любые кнопки ActionBar, которые вы хотели бы
<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>
-
public static 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.height = 850; //fixed height
params.width = 850; //fixed width
params.alpha = 1.0f;
params.dimAmount = 0.5f;
activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
setContentView(R.layout.activity_main);
}
Ответ 2
Если вы используете ActionBarSherlock, объявите тему ниже:
<style name="PopupTheme" parent="Theme.Sherlock">
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
<item name="android:windowActionModeOverlay">true</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowCloseOnTouchOutside">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="windowContentOverlay">@null</item>
</style>
И, инициализируйте SherlockActivity с PopupTheme в соответствии с Ответ Люка Слемана.
private void showAsPopup(SherlockActivity 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); // NO NEED to call this line.
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
LayoutParams params = activity.getWindow().getAttributes();
params.alpha = 1.0f;
params.dimAmount = 0.5f;
activity.getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
// This sets the window size, while working around the IllegalStateException thrown by ActionBarView
activity.getWindow().setLayout(width,height);
}
Результат:
![enter image description here]()
Ответ 3
Были проблемы с реализацией предлагаемых решений от 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 demo (для файла макета см. файл buttons_1.xml в примерах api):
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 (используя MapFragments из API 2). Поэтому моя первая мысль заключалась в том, что из-за попытки открыть из фрагмента возникла проблема, поэтому я передал вызов обратно в свою собственную деятельность. Такая же ошибка, такой же никакой дополнительной информации.
Мое лучшее предположение на этом этапе состояло в том, что вызов 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() в активном создании, а не активном созданном, неясно, как получить экземпляр Activity, который может быть модифицирован ранее на вызов onCreate(). Проблема состоит в том, что вы не можете вызывать такие вещи, как requestWindowFeature() после вызова setContentView() (пример), что является проблемой, поскольку она обычно вызывается в onCreate ().
Опять же, если есть простой/лучший способ сделать это, я очень ценю обратную связь. Надеемся, это поможет людям, которые хотят использовать этот подход.
Ответ 4
Я провел невероятное количество времени, играя с этим. Принятый ответ работает на галактике nexus 7 (Android 4.2), но не работает на галактике SIII (Android 4.1) и галактике Samsung 10.2 (Android 4.0) со следующим исключением:
IllegalStateException: ActionBarView can only be used with android:layout_width="match_parent" (or fill_parent)
Это вызвано кодом в ActionBarView.onMeasure(int, int), который проверяет, чтобы макет был установлен в match_parent. Правильное решение вместо этого задает ширину окна через setLayout вместо использования setAttributes.
Это фиксированная версия 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);
}
Для полноты, вот снова 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>
Ответ 5
Подобно Veeti, вы можете попробовать реализовать Activity с помощью темы Dialog. В манифесте Android:
<activity android:name=".YourActivity" android:theme="@android:style/Theme.Dialog </activity>
Надеюсь, это поможет.
Ответ 6
Я, вероятно, не настолько разбираюсь в этом, но я бы использовал активность, добавлял элементы панели действий, а затем:
<activity android:name=".YourActivity"
android:theme="@android:style/Theme.Holo.Light.Dialog" />
Надеюсь, что это поможет!
Ответ 7
Я знаю, что это не реальный ответ, но выше решения кажутся настолько неэлегантными, что можно подумать, что было бы легче избежать панели действий вообще, например, наследовать тему диалога от чего-то с помощью .noActionBar, а затем создать вид сверху вашей панели, которая имитирует панель действий, по крайней мере таким образом, что все это остается в xlm.
Ответ 8
Я нашел хороший способ сделать это, используя setCustomTitle в построителе alertDialog для DialogFragment (также возможно на самом оповещении).
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity,...);
final Toolbar toolbar = (Toolbar) inflater.inflate(R.layout.dialog_app_filter_toolbar, null, false);
// <= prepare toolbar and dialog here
return builder.create();
}
И результат (от мое приложение):
![введите описание изображения здесь]()
![введите описание изображения здесь]()
Если вы не хотите использовать AlertDialog, вы можете просто поместить панель инструментов в макет диалогового окна и использовать его.