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

AlertDialog setCustomTitle стиль для соответствия стандарту AlertDialog title

Я работаю над Android-приложением, и у меня есть подкласс AlertDialog. Я хотел бы поставить 2 ImageButtons в правой части области заголовка диалогового окна (аналогично ActionBar в Activity). Я использую setCustomTitle() для этого, который заменяет область заголовка специальным представлением моего собственного создания. Это отлично работает, но стиль моей пользовательской области названия не совпадает с стандартным стилем заголовка (высота, цвет, разделитель и т.д.).

Мой вопрос: с пониманием того, что стиль зависит от версии ОС и производителя, как я могу настроить свой пользовательский заголовок в диалоговом окне так, чтобы он соответствовал стандартным стилям заголовка для других AlertDialogs?

Вот изображение anAlertDialog со стандартным стилем (это от ICS, но я хочу иметь возможность сопоставить любой вариант - не этот особый стиль) enter image description here

И вот изображение AlertDialog с настраиваемым заголовком и кнопками (обратите внимание, как высота и цвет заголовка не соответствуют стандартному диалоговому окну) enter image description here

EDIT: я не могу просто добавить ImageButtons в стандартный заголовок, потому что у меня нет доступа к нему. Если вы знаете (надежный, не-hack) метод для добавления кнопок в стандартную область заголовка, я бы тоже согласился с этим.

4b9b3361

Ответ 1

Учитывая, что есть новый интерес к этому вопросу, позвольте мне подробно рассказать о том, как я "решил" это.

Во-первых, я использую ActionBarSherlock в своем приложении. Это не обязательно, я полагаю, хотя это очень помогает, потому что стили и темы, определенные в проекте ABS, позволяют мне подражать теме Holo на устройствах до ICS, что обеспечивает постоянный опыт в приложении.

Во-вторых, мой "диалог" больше не является диалогом - это деятельность, называемая диалогом. Это упрощает манипулирование иерархией представлений, потому что у меня есть полный контроль. Поэтому добавление кнопок в область заголовка теперь тривиально.

Вот скриншоты (2.2 эмулятор устройства и 4.1). Обратите внимание, что единственным существенным отличием стиля является EditText, который я выбрал не для адреса.

2.2 device4.1 emulator

Вот мой onCreate в моей активности в диалоговом режиме:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);

    setContentView(R.layout.activity_tag);
    setTitle(R.string.tag_dialog_title);

    View sherlockTitle = findViewById(android.R.id.title);
    if (sherlockTitle != null) {
        sherlockTitle.setVisibility(View.GONE);
    }
    View sherlockDivider = findViewById(R.id.abs__titleDivider);
    if (sherlockDivider != null) {
        sherlockDivider.setVisibility(View.GONE);
    }

    // setup custom title area
    final View titleArea = findViewById(R.id.dialog_custom_title_area);
    if (titleArea != null) {
        titleArea.setVisibility(View.VISIBLE);

        TextView titleView = (TextView) titleArea.findViewById(R.id.custom_title);
        if (titleView != null) {
            titleView.setText(R.string.tag_dialog_title);
        }

        ImageButton cancelBtn = (ImageButton) titleArea.findViewById(R.id.cancel_btn);
        cancelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        cancelBtn.setVisibility(View.VISIBLE);

        ImageButton okBtn = (ImageButton) titleArea.findViewById(R.id.ok_btn);
        okBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // do stuff here
                finish();
            }
        });
        okBtn.setVisibility(View.VISIBLE);
    }
}

И вот соответствующий макет для деятельности:

<LinearLayout
    android:orientation="vertical"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent">
    <LinearLayout
        android:id="@+id/dialog_custom_title_area"
        android:orientation="vertical"
        android:fitsSystemWindows="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingRight="10dp">
            <TextView
                android:id="@+id/custom_title" style="?android:attr/windowTitleStyle"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:minHeight="@dimen/abs__alert_dialog_title_height"
                android:paddingLeft="16dip"
                android:paddingRight="16dip"
                android:textColor="#ffffff"
                android:gravity="center_vertical|left" />

            <ImageButton
                android:id="@+id/ok_btn"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:minWidth="@dimen/abs__action_button_min_width"
                android:minHeight="@dimen/abs__alert_dialog_title_height"
                android:scaleType="center"
                android:src="@drawable/ic_action_accept"
                android:background="@drawable/abs__item_background_holo_dark"
                android:visibility="visible"
                android:layout_gravity="center_vertical"
                android:contentDescription="@string/acc_done"/>

            <ImageButton
                android:id="@+id/cancel_btn"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:minWidth="@dimen/abs__action_button_min_width"
                android:minHeight="@dimen/abs__alert_dialog_title_height"
                android:scaleType="center"
                android:src="@drawable/ic_action_cancel"
                android:background="@drawable/abs__item_background_holo_dark"
                android:visibility="visible"
                android:layout_gravity="center_vertical"
                android:contentDescription="@string/acc_cancel"
                />
        </LinearLayout>
        <View
            android:id="@+id/dialog_title_divider"
            android:layout_width="fill_parent"
            android:layout_height="2dip"
            android:background="@color/abs__holo_blue_light" />
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/list_suggestions_layout"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">

        <!-- this is where the main dialog area is laid out -->

    </RelativeLayout>

</LinearLayout>

И наконец, в моем AndroidManifext.xml, вот как я определяю свою TagActivity:

<activity 
    android:icon="@drawable/ic_home" 
    android:name=".activity.TagActivity" 
    android:theme="@style/Theme.Sherlock.Dialog"/>

Ответ 2

ОК, может быть, это не супер идеальное решение, и, возможно, это плохое решение, но я пробовал это на Android 2.3.7 и Android 4.1.2:

2.3.7 (real device)

2.3.7 (real device)

4.1.2 (emulator)

4.1.2 (emulator)


Начнем с создания стиля заголовка диалога, чтобы убедиться, что у нас есть место для наших значков:

res/values/dialogstyles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <style name="Dialog" parent="@android:style/Theme.Dialog">
        <item name="android:windowTitleStyle">@style/MyOwnDialogTitle</item>
    </style>

    <style name="MyOwnDialogTitle">
        <!--  we need to make sure our images fit -->
        <item name="android:layout_marginRight">100dp</item>
    </style>

</resources>

res/values-v11/dialogstyles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">

    <style name="Dialog" parent="@android:style/Theme.Holo.Dialog">
        <item name="android:windowTitleStyle">@style/MyOwnDialogTitle</item>
    </style>

</resources>

Затем мы создаем наш DialogFragment двумя трюками:

  • установите стиль в onCreate:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(DialogFragment.STYLE_NORMAL, R.style.Dialog);
    }
    
  • переопределить onCreateView и добавить наш макет (кнопок) в диалог (см. комментарии)

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //we need the view to remove the tree observer (that why it is final)
        final View view = inflater.inflate(R.layout.dialog_custom, container);
        getDialog().setTitle("Shush Dialog");
        //register a layout listener to add our buttons
        view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    
            @SuppressWarnings("deprecation")
            @SuppressLint("NewApi")
            @Override
            public void onGlobalLayout() {
                //inflate our buttons
                View menu = LayoutInflater.from(getActivity()).inflate(R.layout.layout_mymenu, null);
                //get the root view of the Dialog (I am pretty sure this is the weakest link)
                FrameLayout fl = ((FrameLayout) getDialog().getWindow().getDecorView());
                //get the height of the root view (to estimate the height of the title) 
                int height = fl.getHeight() - fl.getPaddingTop() - fl.getPaddingBottom();
                //to estimate the height of the title, we subtract our view height
                //we are sure we have the heights btw because layout is done
                height = height - view.getHeight();
                //prepare the layout params for our view (this includes setting its width)
                //setting the height is not necessary if we ensure it is small
                //we could even add some padding but anyway!
                FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, height);
                params.gravity = Gravity.RIGHT | Gravity.TOP;
                //add the view and we are done
                fl.addView(menu, params);
                if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN)
                    view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                else
                    view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
        return view;
    }
    

Ответ 3

Хорошо, если это только изображения, то вы просто убедитесь, что все, что вы создаете в xml, масштабируется с помощью пикселей плотности или DP для краткости. Самое простое кодирование, которое устанавливает краску, обычно задается пикселями, и может потребоваться версия для ручного кодирования для пикселей плотности.