【问题标题】:AlertDialog setCustomTitle styling to match standard AlertDialog titleAlertDialog setCustomTitle 样式以匹配标准 AlertDialog 标题
【发布时间】:2012-05-25 17:24:49
【问题描述】:

我正在开发一个 Android 应用程序,并且我有一个 AlertDialog 子类。我想在对话框标题区域的右侧放置 2 个 ImageButtons(类似于 Activity 中的 ActionBar)。我正在使用 setCustomTitle() 来执行此操作,它将标题区域替换为我自己创建的自定义视图。这很好用,但我的自定义标题区域的样式与标准标题样式(高度、颜色、分隔符等)不同。

我的问题是:了解样式因操作系统版本和制造商而异,我如何在对话框中设置自定义标题的样式,以使其与其他 AlertDialogs 的标准标题样式匹配?

这是带有标准样式的 anAlertDialog 的图像(来自 ICS,但我希望能够匹配任何变体——不是这种特殊样式)

这是一个带有自定义标题和按钮的 AlertDialog 的图像(请注意标题高度和颜色与标准对话框的不匹配)

编辑:我不能只将 ImageButtons 添加到标准标题视图,因为我无权访问它。 如果您知道我向标准标题区域添加按钮的(可靠、非黑客)方法,我也会接受。

【问题讨论】:

    标签: android android-alertdialog custom-titlebar


    【解决方案1】:

    鉴于对这个问题有新的兴趣,让我详细说明一下我是如何“解决”这个问题的。

    首先,我在我的应用程序中使用ActionBarSherlock。我认为这不是必需的,尽管它很有帮助,因为 ABS 项目中定义的样式和主题允许我在 ICS 之前的设备上模仿 Holo 主题,从而在应用程序中提供一致的体验。

    其次,我的“对话”不再是对话——而是以对话为主题的活动。这使得视图层次结构的操作更简单,因为我拥有完全的控制权。所以现在向标题区域添加按钮很简单。

    这里是屏幕截图(2.2 设备和 4.1 模拟器)。请注意,唯一显着的样式差异是 EditText,我选择不解决。

    这是我的对话活动中的 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)

      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 并将我们的布局(按钮)添加到对话框(参见 cmets)

        @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;
        }
        

      【讨论】:

        【解决方案3】:

        好吧,如果它只是图像,那么您只需确保您在 xml 中创建的所有内容都按密度像素或简称为 DP 进行缩放。大多数设置绘画的简单编码通常也由像素设置,并且可能需要手动编码版本来密度像素。

        【讨论】:

        • 我认为您误解了我要查找的内容。为了清楚起见,我添加了一些图片链接。
        • 我希望这能回答你的问题。
        • 不,我认为您仍然误解了这个问题。 (请参阅我的最新编辑。)我无法通过 ID 访问对话框的标题区域,因此我不能只向其中添加按钮。我必须使用 setCustomTitle(View view),它替换现有的标题区域。
        • 我认为这只是为整体布局包装内容,并在底部视图的缩放方面做了一些变化。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-18
        • 2015-05-23
        • 1970-01-01
        • 2013-02-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多