2012-05-25 1 views
21

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

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

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

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

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

ответ

10

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

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

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

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

2.2 device 4.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

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

+0

Я думаю, вы неправильно поняли, что я ищу. Я добавил некоторые ссылки на изображения для ясности. – mikejonesguy

+0

Надеюсь, это ответит на ваш вопрос. – sdfwer

+1

Нет, я думаю, вы все еще не поняли проблему. (См. Мое последнее редактирование.) Зона заголовка диалогового окна недоступна мне по идентификатору, поэтому я не могу просто добавить к нему свои кнопки. Я должен использовать setCustomTitle (View view), который ** заменяет ** существующую область заголовка. – mikejonesguy

0

ОК, возможно, это не идеальное решение, и, возможно, это плохое решение, но я пробовал это на 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's 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's 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; 
    }