android - studio - El estilo de AlertDialog setCustomTitle coincide con el título estándar de AlertDialog
dialog android tutorial (3)
Estoy trabajando en una aplicación para Android y tengo una subclase de AlertDialog. Me gustaría colocar 2 ImageButtons en el lado derecho del área del título del diálogo (similar a la barra de acción en una actividad). Estoy usando setCustomTitle () para hacer esto, que reemplaza el área del título con una vista personalizada de mi propia creación. Esto funciona bien, pero el estilo de mi área de título personalizado no es el mismo que el estilo de título estándar (altura, color, separador, etc.).
Mi pregunta es: si entiendo que el estilo varía según la versión del sistema operativo y el fabricante , ¿cómo puedo personalizar mi título personalizado en el cuadro de diálogo para que coincida con el estilo de título estándar para otros AlertDialogs?
Aquí hay una imagen de un diálogo de alerta con un estilo estándar (esto es de ICS, pero quiero poder igualar cualquier variante, no este estilo en particular)
Y aquí hay una imagen de un AlertDialog con títulos y botones personalizados (tenga en cuenta que la altura y el color del título no coinciden con el cuadro de diálogo estándar)
EDITAR: No puedo simplemente agregar los ImageButtons a la vista de título estándar, porque no tengo acceso a ellos. Si conoces un método (confiable, que no sea de pirateo) para que yo agregue botones al área de título estándar, también lo aceptaría.
Bueno, tal vez no sea la solución super perfecta y quizás sea una mala solución, pero probé esto en Android 2.3.7 y Android 4.1.2:
2.3.7 (real device)
4.1.2 (emulator)
Comenzamos creando un estilo de título de diálogo para asegurarnos de que tenemos espacio para nuestros iconos:
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>
Luego creamos nuestro DialogFragment con dos trucos:
establece el estilo en el
onCreate
:@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setStyle(DialogFragment.STYLE_NORMAL, R.style.Dialog); }
anular
onCreateView
y agregar nuestro diseño (de botones) al diálogo (ver comentarios)@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; }
Dado que hay un nuevo interés en esta pregunta, permítanme explicar cómo "resolví" esto.
Primero, uso ActionBarSherlock en mi aplicación. Supongo que esto no es necesario, aunque ayuda mucho porque los estilos y temas definidos en el proyecto ABS me permiten imitar el tema Holo en dispositivos pre-ICS, lo que proporciona una experiencia consistente en la aplicación.
En segundo lugar, mi "diálogo" ya no es un diálogo, es una actividad temática como un diálogo. Esto hace que la manipulación de la jerarquía de vistas sea más sencilla, porque tengo el control total. Así que agregar botones al área de título ahora es trivial.
Aquí están las capturas de pantalla (dispositivo 2.2 y emulador 4.1). Tenga en cuenta que la única diferencia de estilo significativa es el EditText, que he elegido no abordar.
Aquí está mi onCreate en mi actividad de diálogo:
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);
}
}
Y aquí está el diseño relevante para la actividad:
<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>
Y finalmente, en mi AndroidManifext.xml, aquí es cómo defino mi TagActivity:
<activity
android:icon="@drawable/ic_home"
android:name=".activity.TagActivity"
android:theme="@style/Theme.Sherlock.Dialog"/>
De acuerdo, si solo se trata de imágenes, solo tienes que asegurarte de que todo lo que creas en xml se escala en píxeles de densidad o DP, para abreviar. La codificación más sencilla que configura la pintura se suele establecer también en píxeles y puede necesitar una versión de codificación manual para densidad de píxeles.