Подтвердить что ты не робот

ActionBar в диалоговом окне диалога

В приложении "Календарь" на моей вкладке Galaxy Tab 10.1 при создании нового события в диалоговом окне появляются кнопки "Готово" и "Отмена" в области заголовка/панели действий.

enter image description here

Я хотел бы реализовать это в своем приложении. Я попытался использовать setHasOptionsMenu(true) в дополнение к переопределению onCreateOptionsMenu в моем подклассе DialogFragment, но мои элементы действия не отображаются. Я также пробовал вызывать getDialog().getActionBar() из onCreateView, но всегда возвращает null.

Я могу получить эту работу, если я начинаю Activity, а не показывая диалог, но это занимает весь экран. Есть ли стандартный способ сделать это, используя DialogFragment?

4b9b3361

Ответ 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, вы можете просто поместить панель инструментов в макет диалогового окна и использовать его.